Stxxl
1.4.0
|
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 ¤t_; 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 ¤t; 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 ¤t; 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 ¤t; 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 ¤t; 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 ¤t; 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 ¤t; 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 ¤t; 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 ¤t; 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 ¤t; 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 ¤t; 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 ¤t; 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