xref: /minix3/external/bsd/bind/dist/unit/atf-src/atf-run/io.hpp (revision 00b67f09dd46474d133c95011a48590a8e8f94c7)
1*00b67f09SDavid van Moolenbroek //
2*00b67f09SDavid van Moolenbroek // Automated Testing Framework (atf)
3*00b67f09SDavid van Moolenbroek //
4*00b67f09SDavid van Moolenbroek // Copyright (c) 2007 The NetBSD Foundation, Inc.
5*00b67f09SDavid van Moolenbroek // All rights reserved.
6*00b67f09SDavid van Moolenbroek //
7*00b67f09SDavid van Moolenbroek // Redistribution and use in source and binary forms, with or without
8*00b67f09SDavid van Moolenbroek // modification, are permitted provided that the following conditions
9*00b67f09SDavid van Moolenbroek // are met:
10*00b67f09SDavid van Moolenbroek // 1. Redistributions of source code must retain the above copyright
11*00b67f09SDavid van Moolenbroek //    notice, this list of conditions and the following disclaimer.
12*00b67f09SDavid van Moolenbroek // 2. Redistributions in binary form must reproduce the above copyright
13*00b67f09SDavid van Moolenbroek //    notice, this list of conditions and the following disclaimer in the
14*00b67f09SDavid van Moolenbroek //    documentation and/or other materials provided with the distribution.
15*00b67f09SDavid van Moolenbroek //
16*00b67f09SDavid van Moolenbroek // THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND
17*00b67f09SDavid van Moolenbroek // CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
18*00b67f09SDavid van Moolenbroek // INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
19*00b67f09SDavid van Moolenbroek // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20*00b67f09SDavid van Moolenbroek // IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY
21*00b67f09SDavid van Moolenbroek // DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22*00b67f09SDavid van Moolenbroek // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
23*00b67f09SDavid van Moolenbroek // GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24*00b67f09SDavid van Moolenbroek // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
25*00b67f09SDavid van Moolenbroek // IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
26*00b67f09SDavid van Moolenbroek // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
27*00b67f09SDavid van Moolenbroek // IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28*00b67f09SDavid van Moolenbroek //
29*00b67f09SDavid van Moolenbroek 
30*00b67f09SDavid van Moolenbroek #if !defined(_ATF_RUN_IO_HPP_)
31*00b67f09SDavid van Moolenbroek #define _ATF_RUN_IO_HPP_
32*00b67f09SDavid van Moolenbroek 
33*00b67f09SDavid van Moolenbroek #include <istream>
34*00b67f09SDavid van Moolenbroek #include <ostream>
35*00b67f09SDavid van Moolenbroek #include <streambuf>
36*00b67f09SDavid van Moolenbroek 
37*00b67f09SDavid van Moolenbroek #include "fs.hpp"
38*00b67f09SDavid van Moolenbroek 
39*00b67f09SDavid van Moolenbroek #include "../atf-c++/detail/auto_array.hpp"
40*00b67f09SDavid van Moolenbroek #include "../atf-c++/noncopyable.hpp"
41*00b67f09SDavid van Moolenbroek 
42*00b67f09SDavid van Moolenbroek namespace atf {
43*00b67f09SDavid van Moolenbroek namespace atf_run {
44*00b67f09SDavid van Moolenbroek 
45*00b67f09SDavid van Moolenbroek // ------------------------------------------------------------------------
46*00b67f09SDavid van Moolenbroek // The "file_handle" class.
47*00b67f09SDavid van Moolenbroek // ------------------------------------------------------------------------
48*00b67f09SDavid van Moolenbroek 
49*00b67f09SDavid van Moolenbroek //!
50*00b67f09SDavid van Moolenbroek //! \brief Simple RAII model for system file handles.
51*00b67f09SDavid van Moolenbroek //!
52*00b67f09SDavid van Moolenbroek //! The \a file_handle class is a simple RAII model for native system file
53*00b67f09SDavid van Moolenbroek //! handles.  This class wraps one of such handles grabbing its ownership,
54*00b67f09SDavid van Moolenbroek //! and automaticaly closes it upon destruction.  It is basically used
55*00b67f09SDavid van Moolenbroek //! inside the library to avoid leaking open file handles, shall an
56*00b67f09SDavid van Moolenbroek //! unexpected execution trace occur.
57*00b67f09SDavid van Moolenbroek //!
58*00b67f09SDavid van Moolenbroek //! A \a file_handle object can be copied but doing so invalidates the
59*00b67f09SDavid van Moolenbroek //! source object.  There can only be a single valid \a file_handle object
60*00b67f09SDavid van Moolenbroek //! for a given system file handle.  This is similar to std::auto_ptr\<\>'s
61*00b67f09SDavid van Moolenbroek //! semantics.
62*00b67f09SDavid van Moolenbroek //!
63*00b67f09SDavid van Moolenbroek //! This class also provides some convenience methods to issue special file
64*00b67f09SDavid van Moolenbroek //! operations under their respective platforms.
65*00b67f09SDavid van Moolenbroek //!
66*00b67f09SDavid van Moolenbroek class file_handle
67*00b67f09SDavid van Moolenbroek {
68*00b67f09SDavid van Moolenbroek public:
69*00b67f09SDavid van Moolenbroek     //!
70*00b67f09SDavid van Moolenbroek     //! \brief Opaque name for the native handle type.
71*00b67f09SDavid van Moolenbroek     //!
72*00b67f09SDavid van Moolenbroek     //! Each operating system identifies file handles using a specific type.
73*00b67f09SDavid van Moolenbroek     //! The \a handle_type type is used to transparently refer to file
74*00b67f09SDavid van Moolenbroek     //! handles regarless of the operating system in which this class is
75*00b67f09SDavid van Moolenbroek     //! used.
76*00b67f09SDavid van Moolenbroek     //!
77*00b67f09SDavid van Moolenbroek     //! If this class is used in a POSIX system, \a NativeSystemHandle is
78*00b67f09SDavid van Moolenbroek     //! an integer type while it is a \a HANDLE in a Win32 system.
79*00b67f09SDavid van Moolenbroek     //!
80*00b67f09SDavid van Moolenbroek     typedef int handle_type;
81*00b67f09SDavid van Moolenbroek 
82*00b67f09SDavid van Moolenbroek     //!
83*00b67f09SDavid van Moolenbroek     //! \brief Constructs an invalid file handle.
84*00b67f09SDavid van Moolenbroek     //!
85*00b67f09SDavid van Moolenbroek     //! This constructor creates a new \a file_handle object that represents
86*00b67f09SDavid van Moolenbroek     //! an invalid file handle.  An invalid file handle can be copied but
87*00b67f09SDavid van Moolenbroek     //! cannot be manipulated in any way (except checking for its validity).
88*00b67f09SDavid van Moolenbroek     //!
89*00b67f09SDavid van Moolenbroek     //! \see is_valid()
90*00b67f09SDavid van Moolenbroek     //!
91*00b67f09SDavid van Moolenbroek     file_handle(void);
92*00b67f09SDavid van Moolenbroek 
93*00b67f09SDavid van Moolenbroek     //!
94*00b67f09SDavid van Moolenbroek     //! \brief Constructs a new file handle from a native file handle.
95*00b67f09SDavid van Moolenbroek     //!
96*00b67f09SDavid van Moolenbroek     //! This constructor creates a new \a file_handle object that takes
97*00b67f09SDavid van Moolenbroek     //! ownership of the given \a h native file handle.  The user must not
98*00b67f09SDavid van Moolenbroek     //! close \a h on his own during the lifetime of the new object.
99*00b67f09SDavid van Moolenbroek     //! Ownership can be reclaimed using disown().
100*00b67f09SDavid van Moolenbroek     //!
101*00b67f09SDavid van Moolenbroek     //! \pre The native file handle must be valid; a close operation must
102*00b67f09SDavid van Moolenbroek     //!      succeed on it.
103*00b67f09SDavid van Moolenbroek     //!
104*00b67f09SDavid van Moolenbroek     //! \see disown()
105*00b67f09SDavid van Moolenbroek     //!
106*00b67f09SDavid van Moolenbroek     file_handle(handle_type h);
107*00b67f09SDavid van Moolenbroek 
108*00b67f09SDavid van Moolenbroek     //!
109*00b67f09SDavid van Moolenbroek     //! \brief Copy constructor; invalidates the source handle.
110*00b67f09SDavid van Moolenbroek     //!
111*00b67f09SDavid van Moolenbroek     //! This copy constructor creates a new file handle from a given one.
112*00b67f09SDavid van Moolenbroek     //! Ownership of the native file handle is transferred to the new
113*00b67f09SDavid van Moolenbroek     //! object, effectively invalidating the source file handle.  This
114*00b67f09SDavid van Moolenbroek     //! avoids having two live \a file_handle objects referring to the
115*00b67f09SDavid van Moolenbroek     //! same native file handle.  The source file handle need not be
116*00b67f09SDavid van Moolenbroek     //! valid in the name of simplicity.
117*00b67f09SDavid van Moolenbroek     //!
118*00b67f09SDavid van Moolenbroek     //! \post The source file handle is invalid.
119*00b67f09SDavid van Moolenbroek     //! \post The new file handle owns the source's native file handle.
120*00b67f09SDavid van Moolenbroek     //!
121*00b67f09SDavid van Moolenbroek     file_handle(const file_handle& fh);
122*00b67f09SDavid van Moolenbroek 
123*00b67f09SDavid van Moolenbroek     //!
124*00b67f09SDavid van Moolenbroek     //! \brief Releases resources if the handle is valid.
125*00b67f09SDavid van Moolenbroek     //!
126*00b67f09SDavid van Moolenbroek     //! If the file handle is valid, the destructor closes it.
127*00b67f09SDavid van Moolenbroek     //!
128*00b67f09SDavid van Moolenbroek     //! \see is_valid()
129*00b67f09SDavid van Moolenbroek     //!
130*00b67f09SDavid van Moolenbroek     ~file_handle(void);
131*00b67f09SDavid van Moolenbroek 
132*00b67f09SDavid van Moolenbroek     //!
133*00b67f09SDavid van Moolenbroek     //! \brief Assignment operator; invalidates the source handle.
134*00b67f09SDavid van Moolenbroek     //!
135*00b67f09SDavid van Moolenbroek     //! This assignment operator transfers ownership of the RHS file
136*00b67f09SDavid van Moolenbroek     //! handle to the LHS one, effectively invalidating the source file
137*00b67f09SDavid van Moolenbroek     //! handle.  This avoids having two live \a file_handle objects
138*00b67f09SDavid van Moolenbroek     //! referring to the same native file handle.  The source file
139*00b67f09SDavid van Moolenbroek     //! handle need not be valid in the name of simplicity.
140*00b67f09SDavid van Moolenbroek     //!
141*00b67f09SDavid van Moolenbroek     //! \post The RHS file handle is invalid.
142*00b67f09SDavid van Moolenbroek     //! \post The LHS file handle owns RHS' native file handle.
143*00b67f09SDavid van Moolenbroek     //! \return A reference to the LHS file handle.
144*00b67f09SDavid van Moolenbroek     //!
145*00b67f09SDavid van Moolenbroek     file_handle& operator=(const file_handle& fh);
146*00b67f09SDavid van Moolenbroek 
147*00b67f09SDavid van Moolenbroek     //!
148*00b67f09SDavid van Moolenbroek     //! \brief Checks whether the file handle is valid or not.
149*00b67f09SDavid van Moolenbroek     //!
150*00b67f09SDavid van Moolenbroek     //! Returns a boolean indicating whether the file handle is valid or
151*00b67f09SDavid van Moolenbroek     //! not.  If the file handle is invalid, no other applications can be
152*00b67f09SDavid van Moolenbroek     //! executed other than the destructor.
153*00b67f09SDavid van Moolenbroek     //!
154*00b67f09SDavid van Moolenbroek     //! \return True if the file handle is valid; false otherwise.
155*00b67f09SDavid van Moolenbroek     //!
156*00b67f09SDavid van Moolenbroek     bool is_valid(void) const;
157*00b67f09SDavid van Moolenbroek 
158*00b67f09SDavid van Moolenbroek     //!
159*00b67f09SDavid van Moolenbroek     //! \brief Closes the file handle.
160*00b67f09SDavid van Moolenbroek     //!
161*00b67f09SDavid van Moolenbroek     //! Explicitly closes the file handle, which must be valid.  Upon
162*00b67f09SDavid van Moolenbroek     //! exit, the handle is not valid any more.
163*00b67f09SDavid van Moolenbroek     //!
164*00b67f09SDavid van Moolenbroek     //! \pre The file handle is valid.
165*00b67f09SDavid van Moolenbroek     //! \post The file handle is invalid.
166*00b67f09SDavid van Moolenbroek     //! \post The native file handle is closed.
167*00b67f09SDavid van Moolenbroek     //!
168*00b67f09SDavid van Moolenbroek     void close(void);
169*00b67f09SDavid van Moolenbroek 
170*00b67f09SDavid van Moolenbroek     //!
171*00b67f09SDavid van Moolenbroek     //! \brief Reclaims ownership of the native file handle.
172*00b67f09SDavid van Moolenbroek     //!
173*00b67f09SDavid van Moolenbroek     //! Explicitly reclaims ownership of the native file handle contained
174*00b67f09SDavid van Moolenbroek     //! in the \a file_handle object, returning the native file handle.
175*00b67f09SDavid van Moolenbroek     //! The caller is responsible of closing it later on.
176*00b67f09SDavid van Moolenbroek     //!
177*00b67f09SDavid van Moolenbroek     //! \pre The file handle is valid.
178*00b67f09SDavid van Moolenbroek     //! \post The file handle is invalid.
179*00b67f09SDavid van Moolenbroek     //! \return The native file handle.
180*00b67f09SDavid van Moolenbroek     //!
181*00b67f09SDavid van Moolenbroek     handle_type disown(void);
182*00b67f09SDavid van Moolenbroek 
183*00b67f09SDavid van Moolenbroek     //!
184*00b67f09SDavid van Moolenbroek     //! \brief Gets the native file handle.
185*00b67f09SDavid van Moolenbroek     //!
186*00b67f09SDavid van Moolenbroek     //! Returns the native file handle for the \a file_handle object.
187*00b67f09SDavid van Moolenbroek     //! The caller can issue any operation on it except closing it.
188*00b67f09SDavid van Moolenbroek     //! If closing is required, disown() shall be used.
189*00b67f09SDavid van Moolenbroek     //!
190*00b67f09SDavid van Moolenbroek     //! \pre The file handle is valid.
191*00b67f09SDavid van Moolenbroek     //! \return The native file handle.
192*00b67f09SDavid van Moolenbroek     //!
193*00b67f09SDavid van Moolenbroek     handle_type get(void) const;
194*00b67f09SDavid van Moolenbroek 
195*00b67f09SDavid van Moolenbroek     //!
196*00b67f09SDavid van Moolenbroek     //! \brief Changes the native file handle to the given one.
197*00b67f09SDavid van Moolenbroek     //!
198*00b67f09SDavid van Moolenbroek     //! Given a new native file handle \a h, this operation assigns this
199*00b67f09SDavid van Moolenbroek     //! handle to the current object, closing its old native file handle.
200*00b67f09SDavid van Moolenbroek     //! In other words, it first calls dup2() to remap the old handle to
201*00b67f09SDavid van Moolenbroek     //! the new one and then closes the old handle.
202*00b67f09SDavid van Moolenbroek     //!
203*00b67f09SDavid van Moolenbroek     //! If \a h matches the current value of the handle, this is a no-op.
204*00b67f09SDavid van Moolenbroek     //! This is done for simplicity, to avoid the caller having to check
205*00b67f09SDavid van Moolenbroek     //! this condition on its own.
206*00b67f09SDavid van Moolenbroek     //!
207*00b67f09SDavid van Moolenbroek     //! If \a h is open, it is automatically closed by dup2().
208*00b67f09SDavid van Moolenbroek     //!
209*00b67f09SDavid van Moolenbroek     //! This operation is only available in POSIX systems.
210*00b67f09SDavid van Moolenbroek     //!
211*00b67f09SDavid van Moolenbroek     //! \pre The file handle is valid.
212*00b67f09SDavid van Moolenbroek     //! \pre The native file handle \a h is valid; i.e., it must be
213*00b67f09SDavid van Moolenbroek     //!      closeable.
214*00b67f09SDavid van Moolenbroek     //! \post The file handle's native file handle is \a h.
215*00b67f09SDavid van Moolenbroek     //! \throw system_error If the internal remapping operation fails.
216*00b67f09SDavid van Moolenbroek     //!
217*00b67f09SDavid van Moolenbroek     void posix_remap(handle_type h);
218*00b67f09SDavid van Moolenbroek 
219*00b67f09SDavid van Moolenbroek private:
220*00b67f09SDavid van Moolenbroek     //!
221*00b67f09SDavid van Moolenbroek     //! \brief Internal handle value.
222*00b67f09SDavid van Moolenbroek     //!
223*00b67f09SDavid van Moolenbroek     //! This variable holds the native handle value for the file handle
224*00b67f09SDavid van Moolenbroek     //! hold by this object.  It is interesting to note that this needs
225*00b67f09SDavid van Moolenbroek     //! to be mutable because the copy constructor and the assignment
226*00b67f09SDavid van Moolenbroek     //! operator invalidate the source object.
227*00b67f09SDavid van Moolenbroek     //!
228*00b67f09SDavid van Moolenbroek     mutable handle_type m_handle;
229*00b67f09SDavid van Moolenbroek 
230*00b67f09SDavid van Moolenbroek     //!
231*00b67f09SDavid van Moolenbroek     //! \brief Constant function representing an invalid handle value.
232*00b67f09SDavid van Moolenbroek     //!
233*00b67f09SDavid van Moolenbroek     //! Returns the platform-specific handle value that represents an
234*00b67f09SDavid van Moolenbroek     //! invalid handle.  This is a constant function rather than a regular
235*00b67f09SDavid van Moolenbroek     //! constant because, in the latter case, we cannot define it under
236*00b67f09SDavid van Moolenbroek     //! Win32 due to the value being of a complex type.
237*00b67f09SDavid van Moolenbroek     //!
238*00b67f09SDavid van Moolenbroek     static handle_type invalid_value(void);
239*00b67f09SDavid van Moolenbroek };
240*00b67f09SDavid van Moolenbroek 
241*00b67f09SDavid van Moolenbroek // ------------------------------------------------------------------------
242*00b67f09SDavid van Moolenbroek // The "systembuf" class.
243*00b67f09SDavid van Moolenbroek // ------------------------------------------------------------------------
244*00b67f09SDavid van Moolenbroek 
245*00b67f09SDavid van Moolenbroek //!
246*00b67f09SDavid van Moolenbroek //! \brief std::streambuf implementation for system file handles.
247*00b67f09SDavid van Moolenbroek //!
248*00b67f09SDavid van Moolenbroek //! systembuf provides a std::streambuf implementation for system file
249*00b67f09SDavid van Moolenbroek //! handles.  Contrarywise to file_handle, this class does \b not take
250*00b67f09SDavid van Moolenbroek //! ownership of the native file handle; this should be taken care of
251*00b67f09SDavid van Moolenbroek //! somewhere else.
252*00b67f09SDavid van Moolenbroek //!
253*00b67f09SDavid van Moolenbroek //! This class follows the expected semantics of a std::streambuf object.
254*00b67f09SDavid van Moolenbroek //! However, it is not copyable to avoid introducing inconsistences with
255*00b67f09SDavid van Moolenbroek //! the on-disk file and the in-memory buffers.
256*00b67f09SDavid van Moolenbroek //!
257*00b67f09SDavid van Moolenbroek class systembuf : public std::streambuf, atf::noncopyable
258*00b67f09SDavid van Moolenbroek {
259*00b67f09SDavid van Moolenbroek public:
260*00b67f09SDavid van Moolenbroek     typedef int handle_type;
261*00b67f09SDavid van Moolenbroek 
262*00b67f09SDavid van Moolenbroek     //!
263*00b67f09SDavid van Moolenbroek     //! \brief Constructs a new systembuf for the given file handle.
264*00b67f09SDavid van Moolenbroek     //!
265*00b67f09SDavid van Moolenbroek     //! This constructor creates a new systembuf object that reads or
266*00b67f09SDavid van Moolenbroek     //! writes data from/to the \a h native file handle.  This handle
267*00b67f09SDavid van Moolenbroek     //! is \b not owned by the created systembuf object; the code
268*00b67f09SDavid van Moolenbroek     //! should take care of it externally.
269*00b67f09SDavid van Moolenbroek     //!
270*00b67f09SDavid van Moolenbroek     //! This class buffers input and output; the buffer size may be
271*00b67f09SDavid van Moolenbroek     //! tuned through the \a bufsize parameter, which defaults to 8192
272*00b67f09SDavid van Moolenbroek     //! bytes.
273*00b67f09SDavid van Moolenbroek     //!
274*00b67f09SDavid van Moolenbroek     //! \see pistream.
275*00b67f09SDavid van Moolenbroek     //!
276*00b67f09SDavid van Moolenbroek     explicit systembuf(handle_type h, std::size_t bufsize = 8192);
277*00b67f09SDavid van Moolenbroek     ~systembuf(void);
278*00b67f09SDavid van Moolenbroek 
279*00b67f09SDavid van Moolenbroek private:
280*00b67f09SDavid van Moolenbroek     //!
281*00b67f09SDavid van Moolenbroek     //! \brief Native file handle used by the systembuf object.
282*00b67f09SDavid van Moolenbroek     //!
283*00b67f09SDavid van Moolenbroek     handle_type m_handle;
284*00b67f09SDavid van Moolenbroek 
285*00b67f09SDavid van Moolenbroek     //!
286*00b67f09SDavid van Moolenbroek     //! \brief Internal buffer size used during read and write operations.
287*00b67f09SDavid van Moolenbroek     //!
288*00b67f09SDavid van Moolenbroek     std::size_t m_bufsize;
289*00b67f09SDavid van Moolenbroek 
290*00b67f09SDavid van Moolenbroek     //!
291*00b67f09SDavid van Moolenbroek     //! \brief Internal buffer used during read operations.
292*00b67f09SDavid van Moolenbroek     //!
293*00b67f09SDavid van Moolenbroek     char* m_read_buf;
294*00b67f09SDavid van Moolenbroek 
295*00b67f09SDavid van Moolenbroek     //!
296*00b67f09SDavid van Moolenbroek     //! \brief Internal buffer used during write operations.
297*00b67f09SDavid van Moolenbroek     //!
298*00b67f09SDavid van Moolenbroek     char* m_write_buf;
299*00b67f09SDavid van Moolenbroek 
300*00b67f09SDavid van Moolenbroek protected:
301*00b67f09SDavid van Moolenbroek     //!
302*00b67f09SDavid van Moolenbroek     //! \brief Reads new data from the native file handle.
303*00b67f09SDavid van Moolenbroek     //!
304*00b67f09SDavid van Moolenbroek     //! This operation is called by input methods when there are no more
305*00b67f09SDavid van Moolenbroek     //! data in the input buffer.  The function fills the buffer with new
306*00b67f09SDavid van Moolenbroek     //! data, if available.
307*00b67f09SDavid van Moolenbroek     //!
308*00b67f09SDavid van Moolenbroek     //! \pre All input positions are exhausted (gptr() >= egptr()).
309*00b67f09SDavid van Moolenbroek     //! \post The input buffer has new data, if available.
310*00b67f09SDavid van Moolenbroek     //! \returns traits_type::eof() if a read error occurrs or there are
311*00b67f09SDavid van Moolenbroek     //!          no more data to be read.  Otherwise returns
312*00b67f09SDavid van Moolenbroek     //!          traits_type::to_int_type(*gptr()).
313*00b67f09SDavid van Moolenbroek     //!
314*00b67f09SDavid van Moolenbroek     virtual int_type underflow(void);
315*00b67f09SDavid van Moolenbroek 
316*00b67f09SDavid van Moolenbroek     //!
317*00b67f09SDavid van Moolenbroek     //! \brief Makes room in the write buffer for additional data.
318*00b67f09SDavid van Moolenbroek     //!
319*00b67f09SDavid van Moolenbroek     //! This operation is called by output methods when there is no more
320*00b67f09SDavid van Moolenbroek     //! space in the output buffer to hold a new element.  The function
321*00b67f09SDavid van Moolenbroek     //! first flushes the buffer's contents to disk and then clears it to
322*00b67f09SDavid van Moolenbroek     //! leave room for more characters.  The given \a c character is
323*00b67f09SDavid van Moolenbroek     //! stored at the beginning of the new space.
324*00b67f09SDavid van Moolenbroek     //!
325*00b67f09SDavid van Moolenbroek     //! \pre All output positions are exhausted (pptr() >= epptr()).
326*00b67f09SDavid van Moolenbroek     //! \post The output buffer has more space if no errors occurred
327*00b67f09SDavid van Moolenbroek     //!       during the write to disk.
328*00b67f09SDavid van Moolenbroek     //! \post *(pptr() - 1) is \a c.
329*00b67f09SDavid van Moolenbroek     //! \returns traits_type::eof() if a write error occurrs.  Otherwise
330*00b67f09SDavid van Moolenbroek     //!          returns traits_type::not_eof(c).
331*00b67f09SDavid van Moolenbroek     //!
332*00b67f09SDavid van Moolenbroek     virtual int_type overflow(int c);
333*00b67f09SDavid van Moolenbroek 
334*00b67f09SDavid van Moolenbroek     //!
335*00b67f09SDavid van Moolenbroek     //! \brief Flushes the output buffer to disk.
336*00b67f09SDavid van Moolenbroek     //!
337*00b67f09SDavid van Moolenbroek     //! Synchronizes the systembuf buffers with the contents of the file
338*00b67f09SDavid van Moolenbroek     //! associated to this object through the native file handle.  The
339*00b67f09SDavid van Moolenbroek     //! output buffer is flushed to disk and cleared to leave new room
340*00b67f09SDavid van Moolenbroek     //! for more data.
341*00b67f09SDavid van Moolenbroek     //!
342*00b67f09SDavid van Moolenbroek     //! \returns 0 on success, -1 if an error occurred.
343*00b67f09SDavid van Moolenbroek     //!
344*00b67f09SDavid van Moolenbroek     virtual int sync(void);
345*00b67f09SDavid van Moolenbroek };
346*00b67f09SDavid van Moolenbroek 
347*00b67f09SDavid van Moolenbroek // ------------------------------------------------------------------------
348*00b67f09SDavid van Moolenbroek // The "pistream" class.
349*00b67f09SDavid van Moolenbroek // ------------------------------------------------------------------------
350*00b67f09SDavid van Moolenbroek 
351*00b67f09SDavid van Moolenbroek //!
352*00b67f09SDavid van Moolenbroek //! \brief Child process' output stream.
353*00b67f09SDavid van Moolenbroek //!
354*00b67f09SDavid van Moolenbroek //! The pistream class represents an output communication channel with the
355*00b67f09SDavid van Moolenbroek //! child process.  The child process writes data to this stream and the
356*00b67f09SDavid van Moolenbroek //! parent process can read it through the pistream object.  In other
357*00b67f09SDavid van Moolenbroek //! words, from the child's point of view, the communication channel is an
358*00b67f09SDavid van Moolenbroek //! output one, but from the parent's point of view it is an input one;
359*00b67f09SDavid van Moolenbroek //! hence the confusing pistream name.
360*00b67f09SDavid van Moolenbroek //!
361*00b67f09SDavid van Moolenbroek //! pistream objects cannot be copied because they own the file handle
362*00b67f09SDavid van Moolenbroek //! they use to communicate with the child and because they buffer data
363*00b67f09SDavid van Moolenbroek //! that flows through the communication channel.
364*00b67f09SDavid van Moolenbroek //!
365*00b67f09SDavid van Moolenbroek //! A pistream object behaves as a std::istream stream in all senses.
366*00b67f09SDavid van Moolenbroek //! The class is only provided because it must provide a method to let
367*00b67f09SDavid van Moolenbroek //! the caller explicitly close the communication channel.
368*00b67f09SDavid van Moolenbroek //!
369*00b67f09SDavid van Moolenbroek //! \remark <b>Blocking remarks</b>: Functions that read data from this
370*00b67f09SDavid van Moolenbroek //! stream can block if the associated file handle blocks during the read.
371*00b67f09SDavid van Moolenbroek //! As this class is used to communicate with child processes through
372*00b67f09SDavid van Moolenbroek //! anonymous pipes, the most typical blocking condition happens when the
373*00b67f09SDavid van Moolenbroek //! child has no more data to send to the pipe's system buffer.  When
374*00b67f09SDavid van Moolenbroek //! this happens, the buffer eventually empties and the system blocks
375*00b67f09SDavid van Moolenbroek //! until the writer generates some data.
376*00b67f09SDavid van Moolenbroek //!
377*00b67f09SDavid van Moolenbroek class pistream : public std::istream, noncopyable
378*00b67f09SDavid van Moolenbroek {
379*00b67f09SDavid van Moolenbroek     //!
380*00b67f09SDavid van Moolenbroek     //! \brief The systembuf object used to manage this stream's data.
381*00b67f09SDavid van Moolenbroek     //!
382*00b67f09SDavid van Moolenbroek     systembuf m_systembuf;
383*00b67f09SDavid van Moolenbroek 
384*00b67f09SDavid van Moolenbroek public:
385*00b67f09SDavid van Moolenbroek     //!
386*00b67f09SDavid van Moolenbroek     //! \brief Creates a new process' output stream.
387*00b67f09SDavid van Moolenbroek     //!
388*00b67f09SDavid van Moolenbroek     //! Given a file handle, this constructor creates a new pistream
389*00b67f09SDavid van Moolenbroek     //! object that owns the given file handle \a fh.  Ownership of
390*00b67f09SDavid van Moolenbroek     //! \a fh is transferred to the created pistream object.
391*00b67f09SDavid van Moolenbroek     //!
392*00b67f09SDavid van Moolenbroek     //! \pre \a fh is valid.
393*00b67f09SDavid van Moolenbroek     //! \post \a fh is invalid.
394*00b67f09SDavid van Moolenbroek     //! \post The new pistream object owns \a fh.
395*00b67f09SDavid van Moolenbroek     //!
396*00b67f09SDavid van Moolenbroek     explicit pistream(const int);
397*00b67f09SDavid van Moolenbroek };
398*00b67f09SDavid van Moolenbroek 
399*00b67f09SDavid van Moolenbroek // ------------------------------------------------------------------------
400*00b67f09SDavid van Moolenbroek // The "muxer" class.
401*00b67f09SDavid van Moolenbroek // ------------------------------------------------------------------------
402*00b67f09SDavid van Moolenbroek 
403*00b67f09SDavid van Moolenbroek class muxer : noncopyable {
404*00b67f09SDavid van Moolenbroek     const int* m_fds;
405*00b67f09SDavid van Moolenbroek     const size_t m_nfds;
406*00b67f09SDavid van Moolenbroek 
407*00b67f09SDavid van Moolenbroek     const size_t m_bufsize;
408*00b67f09SDavid van Moolenbroek     atf::auto_array< std::string > m_buffers;
409*00b67f09SDavid van Moolenbroek 
410*00b67f09SDavid van Moolenbroek protected:
411*00b67f09SDavid van Moolenbroek     virtual void line_callback(const size_t, const std::string&) = 0;
412*00b67f09SDavid van Moolenbroek 
413*00b67f09SDavid van Moolenbroek     size_t read_one(const size_t, const int, std::string&, const bool);
414*00b67f09SDavid van Moolenbroek 
415*00b67f09SDavid van Moolenbroek public:
416*00b67f09SDavid van Moolenbroek     muxer(const int*, const size_t, const size_t bufsize = 1024);
417*00b67f09SDavid van Moolenbroek     virtual ~muxer(void);
418*00b67f09SDavid van Moolenbroek 
419*00b67f09SDavid van Moolenbroek     void mux(volatile const bool&);
420*00b67f09SDavid van Moolenbroek     void flush(void);
421*00b67f09SDavid van Moolenbroek };
422*00b67f09SDavid van Moolenbroek 
423*00b67f09SDavid van Moolenbroek } // namespace atf_run
424*00b67f09SDavid van Moolenbroek } // namespace atf
425*00b67f09SDavid van Moolenbroek 
426*00b67f09SDavid van Moolenbroek #endif // !defined(_ATF_RUN_IO_HPP_)
427