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