Stxxl  1.4.0
include/stxxl/bits/stream/stream.h
Go to the documentation of this file.
00001 /***************************************************************************
00002  *  include/stxxl/bits/stream/stream.h
00003  *
00004  *  Part of the STXXL. See http://stxxl.sourceforge.net
00005  *
00006  *  Copyright (C) 2003-2005 Roman Dementiev <dementiev@mpi-sb.mpg.de>
00007  *  Copyright (C) 2009, 2010 Andreas Beckmann <beckmann@cs.uni-frankfurt.de>
00008  *  Copyright (C) 2010 Johannes Singler <singler@kit.edu>
00009  *
00010  *  Distributed under the Boost Software License, Version 1.0.
00011  *  (See accompanying file LICENSE_1_0.txt or copy at
00012  *  http://www.boost.org/LICENSE_1_0.txt)
00013  **************************************************************************/
00014 
00015 #ifndef STXXL_STREAM_HEADER
00016 #define STXXL_STREAM_HEADER
00017 
00018 #include <stxxl/bits/namespace.h>
00019 #include <stxxl/bits/mng/buf_istream.h>
00020 #include <stxxl/bits/mng/buf_ostream.h>
00021 #include <stxxl/bits/common/tuple.h>
00022 #include <stxxl/vector>
00023 #include <stxxl/bits/compat_unique_ptr.h>
00024 
00025 
00026 #ifndef STXXL_VERBOSE_MATERIALIZE
00027 #define STXXL_VERBOSE_MATERIALIZE STXXL_VERBOSE3
00028 #endif
00029 
00030 
00031 __STXXL_BEGIN_NAMESPACE
00032 
00033 //! \brief Stream package subnamespace
00034 namespace stream
00035 {
00036     //! \weakgroup streampack Stream package
00037     //! Package that enables pipelining of consequent sorts
00038     //! and scans of the external data avoiding the saving the intermediate
00039     //! results on the disk, e.g. the output of a sort can be directly
00040     //! fed into a scan procedure without the need to save it on a disk.
00041     //! All components of the package are contained in the \c stxxl::stream
00042     //! namespace.
00043     //!
00044     //!    STREAM ALGORITHM CONCEPT (Do not confuse with C++ input/output streams)
00045     //!
00046     //! \verbatim
00047     //!
00048     //!    struct stream_algorithm // stream, pipe, whatever
00049     //!    {
00050     //!      typedef some_type value_type;
00051     //!
00052     //!      const value_type & operator * () const; // return current element of the stream
00053     //!      stream_algorithm & operator ++ ();      // go to next element. precondition: empty() == false
00054     //!      bool empty() const;                     // return true if end of stream is reached
00055     //!
00056     //!    };
00057     //! \endverbatim
00058     //!
00059     //! \{
00060 
00061 
00062     ////////////////////////////////////////////////////////////////////////
00063     //     STREAMIFY                                                      //
00064     ////////////////////////////////////////////////////////////////////////
00065 
00066     //! \brief A model of stream that retrieves the data from an input iterator
00067     //! For convenience use \c streamify function instead of direct instantiation
00068     //! of \c iterator2stream .
00069     template <class InputIterator_>
00070     class iterator2stream
00071     {
00072         InputIterator_ current_, end_;
00073 
00074     public:
00075         //! \brief Standard stream typedef
00076         typedef typename std::iterator_traits<InputIterator_>::value_type value_type;
00077 
00078         iterator2stream(InputIterator_ begin, InputIterator_ end) :
00079             current_(begin), end_(end) { }
00080 
00081         iterator2stream(const iterator2stream & a) : current_(a.current_), end_(a.end_) { }
00082 
00083         //! \brief Standard stream method
00084         const value_type & operator * () const
00085         {
00086             return *current_;
00087         }
00088 
00089         const value_type * operator -> () const
00090         {
00091             return &(*current_);
00092         }
00093 
00094         //! \brief Standard stream method
00095         iterator2stream & operator ++ ()
00096         {
00097             assert(end_ != current_);
00098             ++current_;
00099             return *this;
00100         }
00101 
00102         //! \brief Standard stream method
00103         bool empty() const
00104         {
00105             return (current_ == end_);
00106         }
00107     };
00108 
00109 
00110     //! \brief Input iterator range to stream converter
00111     //! \param begin iterator, pointing to the first value
00112     //! \param end iterator, pointing to the last + 1 position, i.e. beyond the range
00113     //! \return an instance of a stream object
00114     template <class InputIterator_>
00115     iterator2stream<InputIterator_> streamify(InputIterator_ begin, InputIterator_ end)
00116     {
00117         return iterator2stream<InputIterator_>(begin, end);
00118     }
00119 
00120     //! \brief Traits class of \c streamify function
00121     template <class InputIterator_>
00122     struct streamify_traits
00123     {
00124         //! \brief return type (stream type) of \c streamify for \c InputIterator_
00125         typedef iterator2stream<InputIterator_> stream_type;
00126     };
00127 
00128     //! \brief A model of stream that retrieves data from an external \c stxxl::vector iterator.
00129     //! It is more efficient than generic \c iterator2stream thanks to use of overlapping
00130     //! For convenience use \c streamify function instead of direct instantiation
00131     //! of \c vector_iterator2stream .
00132     template <class InputIterator_>
00133     class vector_iterator2stream
00134     {
00135         InputIterator_ current_, end_;
00136         typedef buf_istream<typename InputIterator_::block_type,
00137                             typename InputIterator_::bids_container_iterator> buf_istream_type;
00138 
00139         typedef typename stxxl::compat_unique_ptr<buf_istream_type>::result buf_istream_unique_ptr_type;
00140         mutable buf_istream_unique_ptr_type in;
00141 
00142         void delete_stream()
00143         {
00144             in.reset();  // delete object
00145         }
00146 
00147     public:
00148         typedef vector_iterator2stream<InputIterator_> Self_;
00149 
00150         //! \brief Standard stream typedef
00151         typedef typename std::iterator_traits<InputIterator_>::value_type value_type;
00152 
00153         vector_iterator2stream(InputIterator_ begin, InputIterator_ end, unsigned_type nbuffers = 0) :
00154             current_(begin), end_(end), in(static_cast<buf_istream_type *>(NULL))
00155         {
00156             if (empty())
00157                 return;
00158 
00159             begin.flush();     // flush container
00160             typename InputIterator_::bids_container_iterator end_iter = end.bid() + ((end.block_offset()) ? 1 : 0);
00161 
00162             if (end_iter - begin.bid() > 0)
00163             {
00164                 in.reset(new buf_istream_type(begin.bid(), end_iter, nbuffers ? nbuffers :
00165                                               (2 * config::get_instance()->disks_number())));
00166 
00167                 InputIterator_ cur = begin - begin.block_offset();
00168 
00169                 // skip the beginning of the block
00170                 for ( ; cur != begin; ++cur)
00171                     ++(*in);
00172             }
00173         }
00174 
00175         vector_iterator2stream(const Self_ & a) :
00176             current_(a.current_), end_(a.end_), in(a.in.release()) { }
00177 
00178         //! \brief Standard stream method
00179         const value_type & operator * () const
00180         {
00181             return **in;
00182         }
00183 
00184         const value_type * operator -> () const
00185         {
00186             return &(**in);
00187         }
00188 
00189         //! \brief Standard stream method
00190         Self_ & operator ++ ()
00191         {
00192             assert(end_ != current_);
00193             ++current_;
00194             ++(*in);
00195             if (UNLIKELY(empty()))
00196                 delete_stream();
00197 
00198             return *this;
00199         }
00200 
00201         //! \brief Standard stream method
00202         bool empty() const
00203         {
00204             return (current_ == end_);
00205         }
00206         virtual ~vector_iterator2stream()
00207         {
00208             delete_stream();      // not needed actually
00209         }
00210     };
00211 
00212     //! \brief Input external \c stxxl::vector iterator range to stream converter
00213     //! It is more efficient than generic input iterator \c streamify thanks to use of overlapping
00214     //! \param begin iterator, pointing to the first value
00215     //! \param end iterator, pointing to the last + 1 position, i.e. beyond the range
00216     //! \param nbuffers number of blocks used for overlapped reading (0 is default,
00217     //! which equals to (2 * number_of_disks)
00218     //! \return an instance of a stream object
00219 
00220     template <typename Tp_, typename AllocStr_, typename SzTp_, typename DiffTp_,
00221               unsigned BlkSize_, typename PgTp_, unsigned PgSz_>
00222     vector_iterator2stream<stxxl::vector_iterator<Tp_, AllocStr_, SzTp_, DiffTp_, BlkSize_, PgTp_, PgSz_> >
00223     streamify(
00224         stxxl::vector_iterator<Tp_, AllocStr_, SzTp_, DiffTp_, BlkSize_, PgTp_, PgSz_> begin,
00225         stxxl::vector_iterator<Tp_, AllocStr_, SzTp_, DiffTp_, BlkSize_, PgTp_, PgSz_> end,
00226         unsigned_type nbuffers = 0)
00227     {
00228         STXXL_VERBOSE1("streamify for vector_iterator range is called");
00229         return vector_iterator2stream<stxxl::vector_iterator<Tp_, AllocStr_, SzTp_, DiffTp_, BlkSize_, PgTp_, PgSz_> >
00230                    (begin, end, nbuffers);
00231     }
00232 
00233     template <typename Tp_, typename AllocStr_, typename SzTp_, typename DiffTp_,
00234               unsigned BlkSize_, typename PgTp_, unsigned PgSz_>
00235     struct streamify_traits<stxxl::vector_iterator<Tp_, AllocStr_, SzTp_, DiffTp_, BlkSize_, PgTp_, PgSz_> >
00236     {
00237         typedef vector_iterator2stream<stxxl::vector_iterator<Tp_, AllocStr_, SzTp_, DiffTp_, BlkSize_, PgTp_, PgSz_> > stream_type;
00238     };
00239 
00240     //! \brief Input external \c stxxl::vector const iterator range to stream converter
00241     //! It is more efficient than generic input iterator \c streamify thanks to use of overlapping
00242     //! \param begin const iterator, pointing to the first value
00243     //! \param end const iterator, pointing to the last + 1 position, i.e. beyond the range
00244     //! \param nbuffers number of blocks used for overlapped reading (0 is default,
00245     //! which equals to (2 * number_of_disks)
00246     //! \return an instance of a stream object
00247 
00248     template <typename Tp_, typename AllocStr_, typename SzTp_, typename DiffTp_,
00249               unsigned BlkSize_, typename PgTp_, unsigned PgSz_>
00250     vector_iterator2stream<stxxl::const_vector_iterator<Tp_, AllocStr_, SzTp_, DiffTp_, BlkSize_, PgTp_, PgSz_> >
00251     streamify(
00252         stxxl::const_vector_iterator<Tp_, AllocStr_, SzTp_, DiffTp_, BlkSize_, PgTp_, PgSz_> begin,
00253         stxxl::const_vector_iterator<Tp_, AllocStr_, SzTp_, DiffTp_, BlkSize_, PgTp_, PgSz_> end,
00254         unsigned_type nbuffers = 0)
00255     {
00256         STXXL_VERBOSE1("streamify for const_vector_iterator range is called");
00257         return vector_iterator2stream<stxxl::const_vector_iterator<Tp_, AllocStr_, SzTp_, DiffTp_, BlkSize_, PgTp_, PgSz_> >
00258                    (begin, end, nbuffers);
00259     }
00260 
00261     template <typename Tp_, typename AllocStr_, typename SzTp_, typename DiffTp_,
00262               unsigned BlkSize_, typename PgTp_, unsigned PgSz_>
00263     struct streamify_traits<stxxl::const_vector_iterator<Tp_, AllocStr_, SzTp_, DiffTp_, BlkSize_, PgTp_, PgSz_> >
00264     {
00265         typedef vector_iterator2stream<stxxl::const_vector_iterator<Tp_, AllocStr_, SzTp_, DiffTp_, BlkSize_, PgTp_, PgSz_> > stream_type;
00266     };
00267 
00268 
00269     //! \brief Version of  \c iterator2stream. Switches between \c vector_iterator2stream and \c iterator2stream .
00270     //!
00271     //! small range switches between
00272     //! \c vector_iterator2stream and \c iterator2stream .
00273     //! iterator2stream is chosen if the input iterator range
00274     //! is small ( < B )
00275     template <class InputIterator_>
00276     class vector_iterator2stream_sr
00277     {
00278         vector_iterator2stream<InputIterator_> * vec_it_stream;
00279         iterator2stream<InputIterator_> * it_stream;
00280 
00281         typedef typename InputIterator_::block_type block_type;
00282 
00283     public:
00284         typedef vector_iterator2stream_sr<InputIterator_> Self_;
00285 
00286         //! \brief Standard stream typedef
00287         typedef typename std::iterator_traits<InputIterator_>::value_type value_type;
00288 
00289         vector_iterator2stream_sr(InputIterator_ begin, InputIterator_ end, unsigned_type nbuffers = 0)
00290         {
00291             if (end - begin < block_type::size)
00292             {
00293                 STXXL_VERBOSE1("vector_iterator2stream_sr::vector_iterator2stream_sr: Choosing iterator2stream<InputIterator_>");
00294                 it_stream = new iterator2stream<InputIterator_>(begin, end);
00295                 vec_it_stream = NULL;
00296             }
00297             else
00298             {
00299                 STXXL_VERBOSE1("vector_iterator2stream_sr::vector_iterator2stream_sr: Choosing vector_iterator2stream<InputIterator_>");
00300                 it_stream = NULL;
00301                 vec_it_stream = new vector_iterator2stream<InputIterator_>(begin, end, nbuffers);
00302             }
00303         }
00304 
00305         vector_iterator2stream_sr(const Self_ & a) : vec_it_stream(a.vec_it_stream), it_stream(a.it_stream) { }
00306 
00307         //! \brief Standard stream method
00308         const value_type & operator * () const
00309         {
00310             if (it_stream)
00311                 return **it_stream;
00312 
00313             return **vec_it_stream;
00314         }
00315 
00316         const value_type * operator -> () const
00317         {
00318             if (it_stream)
00319                 return &(**it_stream);
00320 
00321             return &(**vec_it_stream);
00322         }
00323 
00324         //! \brief Standard stream method
00325         Self_ & operator ++ ()
00326         {
00327             if (it_stream)
00328                 ++(*it_stream);
00329 
00330             else
00331                 ++(*vec_it_stream);
00332 
00333 
00334             return *this;
00335         }
00336 
00337         //! \brief Standard stream method
00338         bool empty() const
00339         {
00340             if (it_stream)
00341                 return it_stream->empty();
00342 
00343             return vec_it_stream->empty();
00344         }
00345         virtual ~vector_iterator2stream_sr()
00346         {
00347             if (it_stream)
00348                 delete it_stream;
00349 
00350             else
00351                 delete vec_it_stream;
00352         }
00353     };
00354 
00355     //! \brief Version of  \c streamify. Switches from \c vector_iterator2stream to \c iterator2stream for small ranges.
00356     template <typename Tp_, typename AllocStr_, typename SzTp_, typename DiffTp_,
00357               unsigned BlkSize_, typename PgTp_, unsigned PgSz_>
00358     vector_iterator2stream_sr<stxxl::vector_iterator<Tp_, AllocStr_, SzTp_, DiffTp_, BlkSize_, PgTp_, PgSz_> >
00359     streamify_sr(
00360         stxxl::vector_iterator<Tp_, AllocStr_, SzTp_, DiffTp_, BlkSize_, PgTp_, PgSz_> begin,
00361         stxxl::vector_iterator<Tp_, AllocStr_, SzTp_, DiffTp_, BlkSize_, PgTp_, PgSz_> end,
00362         unsigned_type nbuffers = 0)
00363     {
00364         STXXL_VERBOSE1("streamify_sr for vector_iterator range is called");
00365         return vector_iterator2stream_sr<stxxl::vector_iterator<Tp_, AllocStr_, SzTp_, DiffTp_, BlkSize_, PgTp_, PgSz_> >
00366                    (begin, end, nbuffers);
00367     }
00368 
00369     //! \brief Version of  \c streamify. Switches from \c vector_iterator2stream to \c iterator2stream for small ranges.
00370     template <typename Tp_, typename AllocStr_, typename SzTp_, typename DiffTp_,
00371               unsigned BlkSize_, typename PgTp_, unsigned PgSz_>
00372     vector_iterator2stream_sr<stxxl::const_vector_iterator<Tp_, AllocStr_, SzTp_, DiffTp_, BlkSize_, PgTp_, PgSz_> >
00373     streamify_sr(
00374         stxxl::const_vector_iterator<Tp_, AllocStr_, SzTp_, DiffTp_, BlkSize_, PgTp_, PgSz_> begin,
00375         stxxl::const_vector_iterator<Tp_, AllocStr_, SzTp_, DiffTp_, BlkSize_, PgTp_, PgSz_> end,
00376         unsigned_type nbuffers = 0)
00377     {
00378         STXXL_VERBOSE1("streamify_sr for const_vector_iterator range is called");
00379         return vector_iterator2stream_sr<stxxl::const_vector_iterator<Tp_, AllocStr_, SzTp_, DiffTp_, BlkSize_, PgTp_, PgSz_> >
00380                    (begin, end, nbuffers);
00381     }
00382 
00383 
00384     ////////////////////////////////////////////////////////////////////////
00385     //     MATERIALIZE                                                    //
00386     ////////////////////////////////////////////////////////////////////////
00387 
00388     //! \brief Stores consecutively stream content to an output iterator
00389     //! \param in stream to be stored used as source
00390     //! \param out output iterator used as destination
00391     //! \return value of the output iterator after all increments,
00392     //! i.e. points to the first unwritten value
00393     //! \pre Output (range) is large enough to hold the all elements in the input stream
00394     template <class OutputIterator_, class StreamAlgorithm_>
00395     OutputIterator_ materialize(StreamAlgorithm_ & in, OutputIterator_ out)
00396     {
00397         STXXL_VERBOSE_MATERIALIZE(STXXL_PRETTY_FUNCTION_NAME);
00398         while (!in.empty())
00399         {
00400             *out = *in;
00401             ++out;
00402             ++in;
00403         }
00404         return out;
00405     }
00406 
00407 
00408     //! \brief Stores consecutively stream content to an output iterator range \b until end of the stream or end of the iterator range is reached
00409     //! \param in stream to be stored used as source
00410     //! \param outbegin output iterator used as destination
00411     //! \param outend output end iterator, pointing beyond the output range
00412     //! \return value of the output iterator after all increments,
00413     //! i.e. points to the first unwritten value
00414     //! \pre Output range is large enough to hold the all elements in the input stream
00415     //!
00416     //! This function is useful when you do not know the length of the stream beforehand.
00417     template <class OutputIterator_, class StreamAlgorithm_>
00418     OutputIterator_ materialize(StreamAlgorithm_ & in, OutputIterator_ outbegin, OutputIterator_ outend)
00419     {
00420         STXXL_VERBOSE_MATERIALIZE(STXXL_PRETTY_FUNCTION_NAME);
00421         while ((!in.empty()) && outend != outbegin)
00422         {
00423             *outbegin = *in;
00424             ++outbegin;
00425             ++in;
00426         }
00427         return outbegin;
00428     }
00429 
00430 
00431     //! \brief Stores consecutively stream content to an output \c stxxl::vector iterator \b until end of the stream or end of the iterator range is reached
00432     //! \param in stream to be stored used as source
00433     //! \param outbegin output \c stxxl::vector iterator used as destination
00434     //! \param outend output end iterator, pointing beyond the output range
00435     //! \param nbuffers number of blocks used for overlapped writing (0 is default,
00436     //! which equals to (2 * number_of_disks)
00437     //! \return value of the output iterator after all increments,
00438     //! i.e. points to the first unwritten value
00439     //! \pre Output range is large enough to hold the all elements in the input stream
00440     //!
00441     //! This function is useful when you do not know the length of the stream beforehand.
00442     template <typename Tp_, typename AllocStr_, typename SzTp_, typename DiffTp_,
00443               unsigned BlkSize_, typename PgTp_, unsigned PgSz_, class StreamAlgorithm_>
00444     stxxl::vector_iterator<Tp_, AllocStr_, SzTp_, DiffTp_, BlkSize_, PgTp_, PgSz_>
00445     materialize(StreamAlgorithm_ & in,
00446                 stxxl::vector_iterator<Tp_, AllocStr_, SzTp_, DiffTp_, BlkSize_, PgTp_, PgSz_> outbegin,
00447                 stxxl::vector_iterator<Tp_, AllocStr_, SzTp_, DiffTp_, BlkSize_, PgTp_, PgSz_> outend,
00448                 unsigned_type nbuffers = 0)
00449     {
00450         STXXL_VERBOSE_MATERIALIZE(STXXL_PRETTY_FUNCTION_NAME);
00451         typedef stxxl::vector_iterator<Tp_, AllocStr_, SzTp_, DiffTp_, BlkSize_, PgTp_, PgSz_> ExtIterator;
00452         typedef stxxl::const_vector_iterator<Tp_, AllocStr_, SzTp_, DiffTp_, BlkSize_, PgTp_, PgSz_> ConstExtIterator;
00453         typedef buf_ostream<typename ExtIterator::block_type, typename ExtIterator::bids_container_iterator> buf_ostream_type;
00454 
00455 
00456         while (outbegin.block_offset()) //  go to the beginning of the block
00457         //  of the external vector
00458         {
00459             if (in.empty() || outbegin == outend)
00460                 return outbegin;
00461 
00462             *outbegin = *in;
00463             ++outbegin;
00464             ++in;
00465         }
00466 
00467         if (nbuffers == 0)
00468             nbuffers = 2 * config::get_instance()->disks_number();
00469 
00470         outbegin.flush(); // flush container
00471 
00472         // create buffered write stream for blocks
00473         buf_ostream_type outstream(outbegin.bid(), nbuffers);
00474 
00475         assert(outbegin.block_offset() == 0);
00476 
00477         // delay calling block_externally_updated() until the block is
00478         // completely filled (and written out) in outstream
00479         ConstExtIterator prev_block = outbegin;
00480 
00481         while (!in.empty() && outend != outbegin)
00482         {
00483             if (outbegin.block_offset() == 0) {
00484                 if (prev_block != outbegin) {
00485                     prev_block.block_externally_updated();
00486                     prev_block = outbegin;
00487                 }
00488             }
00489 
00490             *outstream = *in;
00491             ++outbegin;
00492             ++outstream;
00493             ++in;
00494         }
00495 
00496         ConstExtIterator const_out = outbegin;
00497 
00498         while (const_out.block_offset()) // filling the rest of the block
00499         {
00500             *outstream = *const_out;
00501             ++const_out;
00502             ++outstream;
00503         }
00504 
00505         if (prev_block != outbegin)
00506             prev_block.block_externally_updated();
00507 
00508         outbegin.flush();
00509 
00510         return outbegin;
00511     }
00512 
00513 
00514     //! \brief Stores consecutively stream content to an output \c stxxl::vector iterator
00515     //! \param in stream to be stored used as source
00516     //! \param out output \c stxxl::vector iterator used as destination
00517     //! \param nbuffers number of blocks used for overlapped writing (0 is default,
00518     //! which equals to (2 * number_of_disks)
00519     //! \return value of the output iterator after all increments,
00520     //! i.e. points to the first unwritten value
00521     //! \pre Output (range) is large enough to hold the all elements in the input stream
00522     template <typename Tp_, typename AllocStr_, typename SzTp_, typename DiffTp_,
00523               unsigned BlkSize_, typename PgTp_, unsigned PgSz_, class StreamAlgorithm_>
00524     stxxl::vector_iterator<Tp_, AllocStr_, SzTp_, DiffTp_, BlkSize_, PgTp_, PgSz_>
00525     materialize(StreamAlgorithm_ & in,
00526                 stxxl::vector_iterator<Tp_, AllocStr_, SzTp_, DiffTp_, BlkSize_, PgTp_, PgSz_> out,
00527                 unsigned_type nbuffers = 0)
00528     {
00529         STXXL_VERBOSE_MATERIALIZE(STXXL_PRETTY_FUNCTION_NAME);
00530         typedef stxxl::vector_iterator<Tp_, AllocStr_, SzTp_, DiffTp_, BlkSize_, PgTp_, PgSz_> ExtIterator;
00531         typedef stxxl::const_vector_iterator<Tp_, AllocStr_, SzTp_, DiffTp_, BlkSize_, PgTp_, PgSz_> ConstExtIterator;
00532         typedef buf_ostream<typename ExtIterator::block_type, typename ExtIterator::bids_container_iterator> buf_ostream_type;
00533 
00534         // on the I/O complexity of "materialize":
00535         // crossing block boundary causes O(1) I/Os
00536         // if you stay in a block, then materialize function accesses only the cache of the
00537         // vector (only one block indeed), amortized complexity should apply here
00538 
00539         while (out.block_offset()) //  go to the beginning of the block
00540         //  of the external vector
00541         {
00542             if (in.empty())
00543                 return out;
00544 
00545             *out = *in;
00546             ++out;
00547             ++in;
00548         }
00549 
00550         if (nbuffers == 0)
00551             nbuffers = 2 * config::get_instance()->disks_number();
00552 
00553 
00554         out.flush(); // flush container
00555 
00556         // create buffered write stream for blocks
00557         buf_ostream_type outstream(out.bid(), nbuffers);
00558 
00559         assert(out.block_offset() == 0);
00560 
00561         // delay calling block_externally_updated() until the block is
00562         // completely filled (and written out) in outstream
00563         ConstExtIterator prev_block = out;
00564 
00565         while (!in.empty())
00566         {
00567             if (out.block_offset() == 0) {
00568                 if (prev_block != out) {
00569                     prev_block.block_externally_updated();
00570                     prev_block = out;
00571                 }
00572             }
00573 
00574             // tells the vector that the block was modified
00575             *outstream = *in;
00576             ++out;
00577             ++outstream;
00578             ++in;
00579         }
00580 
00581         ConstExtIterator const_out = out;
00582 
00583         while (const_out.block_offset())
00584         {
00585             *outstream = *const_out;             // might cause I/Os for loading the page that
00586             ++const_out;                         // contains data beyond out
00587             ++outstream;
00588         }
00589 
00590         if (prev_block != out)
00591             prev_block.block_externally_updated();
00592 
00593         out.flush();
00594 
00595         return out;
00596     }
00597 
00598 
00599     //! \brief Reads stream content and discards it.
00600     //! Useful where you do not need the processed stream anymore,
00601     //! but are just interested in side effects, or just for debugging.
00602     //! \param in input stream
00603     template <class StreamAlgorithm_>
00604     void discard(StreamAlgorithm_ & in)
00605     {
00606         while (!in.empty())
00607         {
00608             *in;
00609             ++in;
00610         }
00611     }
00612 
00613 
00614     ////////////////////////////////////////////////////////////////////////
00615     //     GENERATE                                                       //
00616     ////////////////////////////////////////////////////////////////////////
00617 
00618     //! \brief A model of stream that outputs data from an adaptable generator functor
00619     //! For convenience use \c streamify function instead of direct instantiation
00620     //! of \c generator2stream .
00621     template <class Generator_, typename T = typename Generator_::value_type>
00622     class generator2stream
00623     {
00624     public:
00625         //! \brief Standard stream typedef
00626         typedef T value_type;
00627 
00628     private:
00629         Generator_ gen_;
00630         value_type current_;
00631 
00632     public:
00633         generator2stream(Generator_ g) :
00634             gen_(g), current_(gen_()) { }
00635 
00636         generator2stream(const generator2stream & a) : gen_(a.gen_), current_(a.current_) { }
00637 
00638         //! \brief Standard stream method
00639         const value_type & operator * () const
00640         {
00641             return current_;
00642         }
00643 
00644         const value_type * operator -> () const
00645         {
00646             return &current_;
00647         }
00648 
00649         //! \brief Standard stream method
00650         generator2stream & operator ++ ()
00651         {
00652             current_ = gen_();
00653             return *this;
00654         }
00655 
00656         //! \brief Standard stream method
00657         bool empty() const
00658         {
00659             return false;
00660         }
00661     };
00662 
00663     //! \brief Adaptable generator to stream converter
00664     //! \param gen_ generator object
00665     //! \return an instance of a stream object
00666     template <class Generator_>
00667     generator2stream<Generator_> streamify(Generator_ gen_)
00668     {
00669         return generator2stream<Generator_>(gen_);
00670     }
00671 
00672 
00673     ////////////////////////////////////////////////////////////////////////
00674     //     TRANSFORM                                                      //
00675     ////////////////////////////////////////////////////////////////////////
00676 
00677     struct Stopper { };
00678 
00679     //! \brief Processes (up to) 6 input streams using given operation functor
00680     //!
00681     //! \tparam Operation_ type of the operation (type of an
00682     //! adaptable functor that takes 6 parameters)
00683     //! \tparam Input1_ type of the 1st input
00684     //! \tparam Input2_ type of the 2nd input
00685     //! \tparam Input3_ type of the 3rd input
00686     //! \tparam Input4_ type of the 4th input
00687     //! \tparam Input5_ type of the 5th input
00688     //! \tparam Input6_ type of the 6th input
00689     template <class Operation_,
00690               class Input1_,
00691               class Input2_ = Stopper,
00692               class Input3_ = Stopper,
00693               class Input4_ = Stopper,
00694               class Input5_ = Stopper,
00695               class Input6_ = Stopper
00696               >
00697     class transform
00698     {
00699         Operation_ & op;
00700         Input1_ & i1;
00701         Input2_ & i2;
00702         Input3_ & i3;
00703         Input4_ & i4;
00704         Input5_ & i5;
00705         Input6_ & i6;
00706 
00707     public:
00708         //! \brief Standard stream typedef
00709         typedef typename Operation_::value_type value_type;
00710 
00711     private:
00712         value_type current;
00713 
00714     public:
00715         //! \brief Construction
00716         transform(Operation_ & o, Input1_ & i1_, Input2_ & i2_, Input3_ & i3_, Input4_ & i4_,
00717                   Input5_ & i5_, Input5_ & i6_) :
00718             op(o), i1(i1_), i2(i2_), i3(i3_), i4(i4_), i5(i5_), i6(i6_)
00719         {
00720             if (!empty())
00721                 current = op(*i1, *i2, *i3, *i4, *i5, *i6);
00722         }
00723 
00724         //! \brief Standard stream method
00725         const value_type & operator * () const
00726         {
00727             return current;
00728         }
00729 
00730         const value_type * operator -> () const
00731         {
00732             return &current;
00733         }
00734 
00735         //! \brief Standard stream method
00736         transform & operator ++ ()
00737         {
00738             ++i1;
00739             ++i2;
00740             ++i3;
00741             ++i4;
00742             ++i5;
00743             ++i6;
00744             if (!empty())
00745                 current = op(*i1, *i2, *i3, *i4, *i5, *i6);
00746 
00747             return *this;
00748         }
00749 
00750         //! \brief Standard stream method
00751         bool empty() const
00752         {
00753             return i1.empty() || i2.empty() || i3.empty() ||
00754                    i4.empty() || i5.empty() || i6.empty();
00755         }
00756     };
00757 
00758     // Specializations
00759 
00760     ////////////////////////////////////////////////////////////////////////
00761     //     TRANSFORM (1 input stream)                                     //
00762     ////////////////////////////////////////////////////////////////////////
00763 
00764     //! \brief Processes an input stream using given operation functor
00765     //!
00766     //! \tparam Operation_ type of the operation (type of an
00767     //! adaptable functor that takes 1 parameter)
00768     //! \tparam Input1_ type of the input
00769     //! \remark This is a specialization of \c transform .
00770     template <class Operation_,
00771               class Input1_
00772               >
00773     class transform<Operation_, Input1_, Stopper, Stopper, Stopper, Stopper, Stopper>
00774     {
00775         Operation_ & op;
00776         Input1_ & i1;
00777 
00778     public:
00779         //! \brief Standard stream typedef
00780         typedef typename Operation_::value_type value_type;
00781 
00782     private:
00783         value_type current;
00784 
00785     public:
00786         //! \brief Construction
00787         transform(Operation_ & o, Input1_ & i1_) : op(o), i1(i1_)
00788         {
00789             if (!empty())
00790                 current = op(*i1);
00791         }
00792 
00793         //! \brief Standard stream method
00794         const value_type & operator * () const
00795         {
00796             return current;
00797         }
00798 
00799         const value_type * operator -> () const
00800         {
00801             return &current;
00802         }
00803 
00804         //! \brief Standard stream method
00805         transform & operator ++ ()
00806         {
00807             ++i1;
00808             if (!empty())
00809                 current = op(*i1);
00810 
00811             return *this;
00812         }
00813 
00814         //! \brief Standard stream method
00815         bool empty() const
00816         {
00817             return i1.empty();
00818         }
00819     };
00820 
00821 
00822     ////////////////////////////////////////////////////////////////////////
00823     //     TRANSFORM (2 input streams)                                    //
00824     ////////////////////////////////////////////////////////////////////////
00825 
00826     //! \brief Processes 2 input streams using given operation functor
00827     //!
00828     //! \tparam Operation_ type of the operation (type of an
00829     //! adaptable functor that takes 2 parameters)
00830     //! \tparam Input1_ type of the 1st input
00831     //! \tparam Input2_ type of the 2nd input
00832     //! \remark This is a specialization of \c transform .
00833     template <class Operation_,
00834               class Input1_,
00835               class Input2_
00836               >
00837     class transform<Operation_, Input1_, Input2_, Stopper, Stopper, Stopper, Stopper>
00838     {
00839         Operation_ & op;
00840         Input1_ & i1;
00841         Input2_ & i2;
00842 
00843     public:
00844         //! \brief Standard stream typedef
00845         typedef typename Operation_::value_type value_type;
00846 
00847     private:
00848         value_type current;
00849 
00850     public:
00851         //! \brief Construction
00852         transform(Operation_ & o, Input1_ & i1_, Input2_ & i2_) : op(o), i1(i1_), i2(i2_)
00853         {
00854             if (!empty())
00855                 current = op(*i1, *i2);
00856         }
00857 
00858         //! \brief Standard stream method
00859         const value_type & operator * () const
00860         {
00861             return current;
00862         }
00863 
00864         const value_type * operator -> () const
00865         {
00866             return &current;
00867         }
00868 
00869         //! \brief Standard stream method
00870         transform & operator ++ ()
00871         {
00872             ++i1;
00873             ++i2;
00874             if (!empty())
00875                 current = op(*i1, *i2);
00876 
00877             return *this;
00878         }
00879 
00880         //! \brief Standard stream method
00881         bool empty() const
00882         {
00883             return i1.empty() || i2.empty();
00884         }
00885     };
00886 
00887 
00888     ////////////////////////////////////////////////////////////////////////
00889     //     TRANSFORM (3 input streams)                                    //
00890     ////////////////////////////////////////////////////////////////////////
00891 
00892     //! \brief Processes 3 input streams using given operation functor
00893     //!
00894     //! \tparam Operation_ type of the operation (type of an
00895     //! adaptable functor that takes 3 parameters)
00896     //! \tparam Input1_ type of the 1st input
00897     //! \tparam Input2_ type of the 2nd input
00898     //! \tparam Input3_ type of the 3rd input
00899     //! \remark This is a specialization of \c transform .
00900     template <class Operation_,
00901               class Input1_,
00902               class Input2_,
00903               class Input3_
00904               >
00905     class transform<Operation_, Input1_, Input2_, Input3_, Stopper, Stopper, Stopper>
00906     {
00907         Operation_ & op;
00908         Input1_ & i1;
00909         Input2_ & i2;
00910         Input3_ & i3;
00911 
00912     public:
00913         //! \brief Standard stream typedef
00914         typedef typename Operation_::value_type value_type;
00915 
00916     private:
00917         value_type current;
00918 
00919     public:
00920         //! \brief Construction
00921         transform(Operation_ & o, Input1_ & i1_, Input2_ & i2_, Input3_ & i3_) :
00922             op(o), i1(i1_), i2(i2_), i3(i3_)
00923         {
00924             if (!empty())
00925                 current = op(*i1, *i2, *i3);
00926         }
00927 
00928         //! \brief Standard stream method
00929         const value_type & operator * () const
00930         {
00931             return current;
00932         }
00933 
00934         const value_type * operator -> () const
00935         {
00936             return &current;
00937         }
00938 
00939         //! \brief Standard stream method
00940         transform & operator ++ ()
00941         {
00942             ++i1;
00943             ++i2;
00944             ++i3;
00945             if (!empty())
00946                 current = op(*i1, *i2, *i3);
00947 
00948             return *this;
00949         }
00950 
00951         //! \brief Standard stream method
00952         bool empty() const
00953         {
00954             return i1.empty() || i2.empty() || i3.empty();
00955         }
00956     };
00957 
00958 
00959     ////////////////////////////////////////////////////////////////////////
00960     //     TRANSFORM (4 input streams)                                    //
00961     ////////////////////////////////////////////////////////////////////////
00962 
00963     //! \brief Processes 4 input streams using given operation functor
00964     //!
00965     //! \tparam Operation_ type of the operation (type of an
00966     //! adaptable functor that takes 4 parameters)
00967     //! \tparam Input1_ type of the 1st input
00968     //! \tparam Input2_ type of the 2nd input
00969     //! \tparam Input3_ type of the 3rd input
00970     //! \tparam Input4_ type of the 4th input
00971     //! \remark This is a specialization of \c transform .
00972     template <class Operation_,
00973               class Input1_,
00974               class Input2_,
00975               class Input3_,
00976               class Input4_
00977               >
00978     class transform<Operation_, Input1_, Input2_, Input3_, Input4_, Stopper, Stopper>
00979     {
00980         Operation_ & op;
00981         Input1_ & i1;
00982         Input2_ & i2;
00983         Input3_ & i3;
00984         Input4_ & i4;
00985 
00986     public:
00987         //! \brief Standard stream typedef
00988         typedef typename Operation_::value_type value_type;
00989 
00990     private:
00991         value_type current;
00992 
00993     public:
00994         //! \brief Construction
00995         transform(Operation_ & o, Input1_ & i1_, Input2_ & i2_, Input3_ & i3_, Input4_ & i4_) :
00996             op(o), i1(i1_), i2(i2_), i3(i3_), i4(i4_)
00997         {
00998             if (!empty())
00999                 current = op(*i1, *i2, *i3, *i4);
01000         }
01001 
01002         //! \brief Standard stream method
01003         const value_type & operator * () const
01004         {
01005             return current;
01006         }
01007 
01008         const value_type * operator -> () const
01009         {
01010             return &current;
01011         }
01012 
01013         //! \brief Standard stream method
01014         transform & operator ++ ()
01015         {
01016             ++i1;
01017             ++i2;
01018             ++i3;
01019             ++i4;
01020             if (!empty())
01021                 current = op(*i1, *i2, *i3, *i4);
01022 
01023             return *this;
01024         }
01025 
01026         //! \brief Standard stream method
01027         bool empty() const
01028         {
01029             return i1.empty() || i2.empty() || i3.empty() || i4.empty();
01030         }
01031     };
01032 
01033 
01034     ////////////////////////////////////////////////////////////////////////
01035     //     TRANSFORM (5 input streams)                                    //
01036     ////////////////////////////////////////////////////////////////////////
01037 
01038     //! \brief Processes 5 input streams using given operation functor
01039     //!
01040     //! \tparam Operation_ type of the operation (type of an
01041     //! adaptable functor that takes 5 parameters)
01042     //! \tparam Input1_ type of the 1st input
01043     //! \tparam Input2_ type of the 2nd input
01044     //! \tparam Input3_ type of the 3rd input
01045     //! \tparam Input4_ type of the 4th input
01046     //! \tparam Input5_ type of the 5th input
01047     //! \remark This is a specialization of \c transform .
01048     template <class Operation_,
01049               class Input1_,
01050               class Input2_,
01051               class Input3_,
01052               class Input4_,
01053               class Input5_
01054               >
01055     class transform<Operation_, Input1_, Input2_, Input3_, Input4_, Input5_, Stopper>
01056     {
01057         Operation_ & op;
01058         Input1_ & i1;
01059         Input2_ & i2;
01060         Input3_ & i3;
01061         Input4_ & i4;
01062         Input5_ & i5;
01063 
01064     public:
01065         //! \brief Standard stream typedef
01066         typedef typename Operation_::value_type value_type;
01067 
01068     private:
01069         value_type current;
01070 
01071     public:
01072         //! \brief Construction
01073         transform(Operation_ & o, Input1_ & i1_, Input2_ & i2_, Input3_ & i3_, Input4_ & i4_,
01074                   Input5_ & i5_) :
01075             op(o), i1(i1_), i2(i2_), i3(i3_), i4(i4_), i5(i5_)
01076         {
01077             if (!empty())
01078                 current = op(*i1, *i2, *i3, *i4, *i5);
01079         }
01080 
01081         //! \brief Standard stream method
01082         const value_type & operator * () const
01083         {
01084             return current;
01085         }
01086 
01087         const value_type * operator -> () const
01088         {
01089             return &current;
01090         }
01091 
01092         //! \brief Standard stream method
01093         transform & operator ++ ()
01094         {
01095             ++i1;
01096             ++i2;
01097             ++i3;
01098             ++i4;
01099             ++i5;
01100             if (!empty())
01101                 current = op(*i1, *i2, *i3, *i4, *i5);
01102 
01103             return *this;
01104         }
01105 
01106         //! \brief Standard stream method
01107         bool empty() const
01108         {
01109             return i1.empty() || i2.empty() || i3.empty() || i4.empty() || i5.empty();
01110         }
01111     };
01112 
01113 
01114     ////////////////////////////////////////////////////////////////////////
01115     //     MAKE TUPLE                                                     //
01116     ////////////////////////////////////////////////////////////////////////
01117 
01118     //! \brief Creates stream of 6-tuples from 6 input streams
01119     //!
01120     //! \tparam Input1_ type of the 1st input
01121     //! \tparam Input2_ type of the 2nd input
01122     //! \tparam Input3_ type of the 3rd input
01123     //! \tparam Input4_ type of the 4th input
01124     //! \tparam Input5_ type of the 5th input
01125     //! \tparam Input6_ type of the 6th input
01126     template <class Input1_,
01127               class Input2_,
01128               class Input3_ = Stopper,
01129               class Input4_ = Stopper,
01130               class Input5_ = Stopper,
01131               class Input6_ = Stopper
01132               >
01133     class make_tuple
01134     {
01135         Input1_ & i1;
01136         Input2_ & i2;
01137         Input3_ & i3;
01138         Input4_ & i4;
01139         Input5_ & i5;
01140         Input6_ & i6;
01141 
01142     public:
01143         //! \brief Standard stream typedef
01144         typedef typename stxxl::tuple<
01145             typename Input1_::value_type,
01146             typename Input2_::value_type,
01147             typename Input3_::value_type,
01148             typename Input4_::value_type,
01149             typename Input5_::value_type,
01150             typename Input6_::value_type
01151             > value_type;
01152 
01153     private:
01154         value_type current;
01155 
01156     public:
01157         //! \brief Construction
01158         make_tuple(
01159             Input1_ & i1_,
01160             Input2_ & i2_,
01161             Input3_ & i3_,
01162             Input4_ & i4_,
01163             Input5_ & i5_,
01164             Input6_ & i6_
01165             ) :
01166             i1(i1_), i2(i2_), i3(i3_), i4(i4_), i5(i5_), i6(i6_)
01167         {
01168             if (!empty())
01169                 current = value_type(*i1, *i2, *i3, *i4, *i5, *i6);
01170         }
01171 
01172         //! \brief Standard stream method
01173         const value_type & operator * () const
01174         {
01175             return current;
01176         }
01177 
01178         const value_type * operator -> () const
01179         {
01180             return &current;
01181         }
01182 
01183         //! \brief Standard stream method
01184         make_tuple & operator ++ ()
01185         {
01186             ++i1;
01187             ++i2;
01188             ++i3;
01189             ++i4;
01190             ++i5;
01191             ++i6;
01192 
01193             if (!empty())
01194                 current = value_type(*i1, *i2, *i3, *i4, *i5, *i6);
01195 
01196             return *this;
01197         }
01198 
01199         //! \brief Standard stream method
01200         bool empty() const
01201         {
01202             return i1.empty() || i2.empty() || i3.empty() ||
01203                    i4.empty() || i5.empty() || i6.empty();
01204         }
01205     };
01206 
01207 
01208     //! \brief Creates stream of 2-tuples (pairs) from 2 input streams
01209     //!
01210     //! \tparam Input1_ type of the 1st input
01211     //! \tparam Input2_ type of the 2nd input
01212     //! \remark A specialization of \c make_tuple .
01213     template <class Input1_,
01214               class Input2_
01215               >
01216     class make_tuple<Input1_, Input2_, Stopper, Stopper, Stopper, Stopper>
01217     {
01218         Input1_ & i1;
01219         Input2_ & i2;
01220 
01221     public:
01222         //! \brief Standard stream typedef
01223         typedef typename stxxl::tuple<
01224             typename Input1_::value_type,
01225             typename Input2_::value_type
01226             > value_type;
01227 
01228     private:
01229         value_type current;
01230 
01231     public:
01232         //! \brief Construction
01233         make_tuple(
01234             Input1_ & i1_,
01235             Input2_ & i2_
01236             ) :
01237             i1(i1_), i2(i2_)
01238         {
01239             if (!empty())
01240             {
01241                 current = value_type(*i1, *i2);
01242             }
01243         }
01244 
01245         //! \brief Standard stream method
01246         const value_type & operator * () const
01247         {
01248             return current;
01249         }
01250 
01251         const value_type * operator -> () const
01252         {
01253             return &current;
01254         }
01255 
01256         //! \brief Standard stream method
01257         make_tuple & operator ++ ()
01258         {
01259             ++i1;
01260             ++i2;
01261 
01262             if (!empty())
01263                 current = value_type(*i1, *i2);
01264 
01265             return *this;
01266         }
01267 
01268         //! \brief Standard stream method
01269         bool empty() const
01270         {
01271             return i1.empty() || i2.empty();
01272         }
01273     };
01274 
01275     //! \brief Creates stream of 3-tuples from 3 input streams
01276     //!
01277     //! \tparam Input1_ type of the 1st input
01278     //! \tparam Input2_ type of the 2nd input
01279     //! \tparam Input3_ type of the 3rd input
01280     //! \remark A specialization of \c make_tuple .
01281     template <class Input1_,
01282               class Input2_,
01283               class Input3_
01284               >
01285     class make_tuple<Input1_, Input2_, Input3_, Stopper, Stopper, Stopper>
01286     {
01287         Input1_ & i1;
01288         Input2_ & i2;
01289         Input3_ & i3;
01290 
01291     public:
01292         //! \brief Standard stream typedef
01293         typedef typename stxxl::tuple<
01294             typename Input1_::value_type,
01295             typename Input2_::value_type,
01296             typename Input3_::value_type
01297             > value_type;
01298 
01299     private:
01300         value_type current;
01301 
01302     public:
01303         //! \brief Construction
01304         make_tuple(
01305             Input1_ & i1_,
01306             Input2_ & i2_,
01307             Input3_ & i3_
01308             ) :
01309             i1(i1_), i2(i2_), i3(i3_)
01310         {
01311             if (!empty())
01312                 current = value_type(*i1, *i2, *i3);
01313         }
01314 
01315         //! \brief Standard stream method
01316         const value_type & operator * () const
01317         {
01318             return current;
01319         }
01320 
01321         const value_type * operator -> () const
01322         {
01323             return &current;
01324         }
01325 
01326         //! \brief Standard stream method
01327         make_tuple & operator ++ ()
01328         {
01329             ++i1;
01330             ++i2;
01331             ++i3;
01332 
01333             if (!empty())
01334                 current = value_type(*i1, *i2, *i3);
01335 
01336             return *this;
01337         }
01338 
01339         //! \brief Standard stream method
01340         bool empty() const
01341         {
01342             return i1.empty() || i2.empty() || i3.empty();
01343         }
01344     };
01345 
01346     //! \brief Creates stream of 4-tuples from 4 input streams
01347     //!
01348     //! \tparam Input1_ type of the 1st input
01349     //! \tparam Input2_ type of the 2nd input
01350     //! \tparam Input3_ type of the 3rd input
01351     //! \tparam Input4_ type of the 4th input
01352     //! \remark A specialization of \c make_tuple .
01353     template <class Input1_,
01354               class Input2_,
01355               class Input3_,
01356               class Input4_
01357               >
01358     class make_tuple<Input1_, Input2_, Input3_, Input4_, Stopper, Stopper>
01359     {
01360         Input1_ & i1;
01361         Input2_ & i2;
01362         Input3_ & i3;
01363         Input4_ & i4;
01364 
01365     public:
01366         //! \brief Standard stream typedef
01367         typedef typename stxxl::tuple<
01368             typename Input1_::value_type,
01369             typename Input2_::value_type,
01370             typename Input3_::value_type,
01371             typename Input4_::value_type
01372             > value_type;
01373 
01374     private:
01375         value_type current;
01376 
01377     public:
01378         //! \brief Construction
01379         make_tuple(
01380             Input1_ & i1_,
01381             Input2_ & i2_,
01382             Input3_ & i3_,
01383             Input4_ & i4_
01384             ) :
01385             i1(i1_), i2(i2_), i3(i3_), i4(i4_)
01386         {
01387             if (!empty())
01388                 current = value_type(*i1, *i2, *i3, *i4);
01389         }
01390 
01391         //! \brief Standard stream method
01392         const value_type & operator * () const
01393         {
01394             return current;
01395         }
01396 
01397         const value_type * operator -> () const
01398         {
01399             return &current;
01400         }
01401 
01402         //! \brief Standard stream method
01403         make_tuple & operator ++ ()
01404         {
01405             ++i1;
01406             ++i2;
01407             ++i3;
01408             ++i4;
01409 
01410             if (!empty())
01411                 current = value_type(*i1, *i2, *i3, *i4);
01412 
01413             return *this;
01414         }
01415 
01416         //! \brief Standard stream method
01417         bool empty() const
01418         {
01419             return i1.empty() || i2.empty() || i3.empty() ||
01420                    i4.empty();
01421         }
01422     };
01423 
01424     //! \brief Creates stream of 5-tuples from 5 input streams
01425     //!
01426     //! \tparam Input1_ type of the 1st input
01427     //! \tparam Input2_ type of the 2nd input
01428     //! \tparam Input3_ type of the 3rd input
01429     //! \tparam Input4_ type of the 4th input
01430     //! \tparam Input5_ type of the 5th input
01431     //! \remark A specialization of \c make_tuple .
01432     template <
01433         class Input1_,
01434         class Input2_,
01435         class Input3_,
01436         class Input4_,
01437         class Input5_
01438         >
01439     class make_tuple<Input1_, Input2_, Input3_, Input4_, Input5_, Stopper>
01440     {
01441         Input1_ & i1;
01442         Input2_ & i2;
01443         Input3_ & i3;
01444         Input4_ & i4;
01445         Input5_ & i5;
01446 
01447     public:
01448         //! \brief Standard stream typedef
01449         typedef typename stxxl::tuple<
01450             typename Input1_::value_type,
01451             typename Input2_::value_type,
01452             typename Input3_::value_type,
01453             typename Input4_::value_type,
01454             typename Input5_::value_type
01455             > value_type;
01456 
01457     private:
01458         value_type current;
01459 
01460     public:
01461         //! \brief Construction
01462         make_tuple(
01463             Input1_ & i1_,
01464             Input2_ & i2_,
01465             Input3_ & i3_,
01466             Input4_ & i4_,
01467             Input5_ & i5_
01468             ) :
01469             i1(i1_), i2(i2_), i3(i3_), i4(i4_), i5(i5_)
01470         {
01471             if (!empty())
01472                 current = value_type(*i1, *i2, *i3, *i4, *i5);
01473         }
01474 
01475         //! \brief Standard stream method
01476         const value_type & operator * () const
01477         {
01478             return current;
01479         }
01480 
01481         const value_type * operator -> () const
01482         {
01483             return &current;
01484         }
01485 
01486         //! \brief Standard stream method
01487         make_tuple & operator ++ ()
01488         {
01489             ++i1;
01490             ++i2;
01491             ++i3;
01492             ++i4;
01493             ++i5;
01494 
01495             if (!empty())
01496                 current = value_type(*i1, *i2, *i3, *i4, *i5);
01497 
01498             return *this;
01499         }
01500 
01501         //! \brief Standard stream method
01502         bool empty() const
01503         {
01504             return i1.empty() || i2.empty() || i3.empty() ||
01505                    i4.empty() || i5.empty();
01506         }
01507     };
01508 
01509 
01510 //! \}
01511 }
01512 
01513 __STXXL_END_NAMESPACE
01514 
01515 
01516 #include <stxxl/bits/stream/choose.h>
01517 #include <stxxl/bits/stream/unique.h>
01518 
01519 
01520 #endif // !STXXL_STREAM_HEADER
01521 // vim: et:ts=4:sw=4
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines