• Main Page
  • Related Pages
  • Modules
  • Namespaces
  • Classes
  • Files
  • Examples
  • File List

stream.h

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 <[email protected]>
00007  *
00008  *  Distributed under the Boost Software License, Version 1.0.
00009  *  (See accompanying file LICENSE_1_0.txt or copy at
00010  *  http://www.boost.org/LICENSE_1_0.txt)
00011  **************************************************************************/
00012 
00013 #ifndef STXXL_STREAM_HEADER
00014 #define STXXL_STREAM_HEADER
00015 
00016 #include <stxxl/bits/namespace.h>
00017 #include <stxxl/bits/mng/buf_istream.h>
00018 #include <stxxl/bits/mng/buf_ostream.h>
00019 #include <stxxl/bits/common/tuple.h>
00020 #include <stxxl/vector>
00021 #include <stxxl/bits/compat_unique_ptr.h>
00022 
00023 
00024 #ifndef STXXL_VERBOSE_MATERIALIZE
00025 #define STXXL_VERBOSE_MATERIALIZE STXXL_VERBOSE3
00026 #endif
00027 
00028 
00029 __STXXL_BEGIN_NAMESPACE
00030 
00032 namespace stream
00033 {
00058 
00059 
00061     //     STREAMIFY                                                      //
00063 
00067     template <class InputIterator_>
00068     class iterator2stream
00069     {
00070         InputIterator_ current_, end_;
00071 
00072     public:
00074         typedef typename std::iterator_traits<InputIterator_>::value_type value_type;
00075 
00076         iterator2stream(InputIterator_ begin, InputIterator_ end) :
00077             current_(begin), end_(end) { }
00078 
00079         iterator2stream(const iterator2stream & a) : current_(a.current_), end_(a.end_) { }
00080 
00082         const value_type & operator * () const
00083         {
00084             return *current_;
00085         }
00086 
00087         const value_type * operator -> () const
00088         {
00089             return &(*current_);
00090         }
00091 
00093         iterator2stream & operator ++ ()
00094         {
00095             assert(end_ != current_);
00096             ++current_;
00097             return *this;
00098         }
00099 
00101         bool empty() const
00102         {
00103             return (current_ == end_);
00104         }
00105     };
00106 
00107 
00112     template <class InputIterator_>
00113     iterator2stream<InputIterator_> streamify(InputIterator_ begin, InputIterator_ end)
00114     {
00115         return iterator2stream<InputIterator_>(begin, end);
00116     }
00117 
00119     template <class InputIterator_>
00120     struct streamify_traits
00121     {
00123         typedef iterator2stream<InputIterator_> stream_type;
00124     };
00125 
00130     template <class InputIterator_>
00131     class vector_iterator2stream
00132     {
00133         InputIterator_ current_, end_;
00134         typedef buf_istream<typename InputIterator_::block_type,
00135                             typename InputIterator_::bids_container_iterator> buf_istream_type;
00136 
00137         typedef typename stxxl::compat_unique_ptr<buf_istream_type>::result buf_istream_unique_ptr_type;
00138         mutable buf_istream_unique_ptr_type in;
00139 
00140         void delete_stream()
00141         {
00142             in.reset();  // delete object
00143         }
00144 
00145     public:
00146         typedef vector_iterator2stream<InputIterator_> Self_;
00147 
00149         typedef typename std::iterator_traits<InputIterator_>::value_type value_type;
00150 
00151         vector_iterator2stream(InputIterator_ begin, InputIterator_ end, unsigned_type nbuffers = 0) :
00152             current_(begin), end_(end), in(static_cast<buf_istream_type *>(NULL))
00153         {
00154             begin.flush();     // flush container
00155             typename InputIterator_::bids_container_iterator end_iter = end.bid() + ((end.block_offset()) ? 1 : 0);
00156 
00157             if (end_iter - begin.bid() > 0)
00158             {
00159                 in.reset(new buf_istream_type(begin.bid(), end_iter, nbuffers ? nbuffers :
00160                                               (2 * config::get_instance()->disks_number())));
00161 
00162                 InputIterator_ cur = begin - begin.block_offset();
00163 
00164                 // skip the beginning of the block
00165                 for ( ; cur != begin; ++cur)
00166                     ++(*in);
00167             }
00168         }
00169 
00170         vector_iterator2stream(const Self_ & a) :
00171             current_(a.current_), end_(a.end_), in(a.in.release()) { }
00172 
00174         const value_type & operator * () const
00175         {
00176             return **in;
00177         }
00178 
00179         const value_type * operator -> () const
00180         {
00181             return &(**in);
00182         }
00183 
00185         Self_ & operator ++ ()
00186         {
00187             assert(end_ != current_);
00188             ++current_;
00189             ++(*in);
00190             if (empty())
00191                 delete_stream();
00192 
00193             return *this;
00194         }
00195 
00197         bool empty() const
00198         {
00199             return (current_ == end_);
00200         }
00201         virtual ~vector_iterator2stream()
00202         {
00203             delete_stream();      // not needed actually
00204         }
00205     };
00206 
00214 
00215     template <typename Tp_, typename AllocStr_, typename SzTp_, typename DiffTp_,
00216               unsigned BlkSize_, typename PgTp_, unsigned PgSz_>
00217     vector_iterator2stream<stxxl::vector_iterator<Tp_, AllocStr_, SzTp_, DiffTp_, BlkSize_, PgTp_, PgSz_> >
00218     streamify(
00219         stxxl::vector_iterator<Tp_, AllocStr_, SzTp_, DiffTp_, BlkSize_, PgTp_, PgSz_> begin,
00220         stxxl::vector_iterator<Tp_, AllocStr_, SzTp_, DiffTp_, BlkSize_, PgTp_, PgSz_> end,
00221         unsigned_type nbuffers = 0)
00222     {
00223         STXXL_VERBOSE1("streamify for vector_iterator range is called");
00224         return vector_iterator2stream<stxxl::vector_iterator<Tp_, AllocStr_, SzTp_, DiffTp_, BlkSize_, PgTp_, PgSz_> >
00225                    (begin, end, nbuffers);
00226     }
00227 
00228     template <typename Tp_, typename AllocStr_, typename SzTp_, typename DiffTp_,
00229               unsigned BlkSize_, typename PgTp_, unsigned PgSz_>
00230     struct streamify_traits<stxxl::vector_iterator<Tp_, AllocStr_, SzTp_, DiffTp_, BlkSize_, PgTp_, PgSz_> >
00231     {
00232         typedef vector_iterator2stream<stxxl::vector_iterator<Tp_, AllocStr_, SzTp_, DiffTp_, BlkSize_, PgTp_, PgSz_> > stream_type;
00233     };
00234 
00242 
00243     template <typename Tp_, typename AllocStr_, typename SzTp_, typename DiffTp_,
00244               unsigned BlkSize_, typename PgTp_, unsigned PgSz_>
00245     vector_iterator2stream<stxxl::const_vector_iterator<Tp_, AllocStr_, SzTp_, DiffTp_, BlkSize_, PgTp_, PgSz_> >
00246     streamify(
00247         stxxl::const_vector_iterator<Tp_, AllocStr_, SzTp_, DiffTp_, BlkSize_, PgTp_, PgSz_> begin,
00248         stxxl::const_vector_iterator<Tp_, AllocStr_, SzTp_, DiffTp_, BlkSize_, PgTp_, PgSz_> end,
00249         unsigned_type nbuffers = 0)
00250     {
00251         STXXL_VERBOSE1("streamify for const_vector_iterator range is called");
00252         return vector_iterator2stream<stxxl::const_vector_iterator<Tp_, AllocStr_, SzTp_, DiffTp_, BlkSize_, PgTp_, PgSz_> >
00253                    (begin, end, nbuffers);
00254     }
00255 
00256     template <typename Tp_, typename AllocStr_, typename SzTp_, typename DiffTp_,
00257               unsigned BlkSize_, typename PgTp_, unsigned PgSz_>
00258     struct streamify_traits<stxxl::const_vector_iterator<Tp_, AllocStr_, SzTp_, DiffTp_, BlkSize_, PgTp_, PgSz_> >
00259     {
00260         typedef vector_iterator2stream<stxxl::const_vector_iterator<Tp_, AllocStr_, SzTp_, DiffTp_, BlkSize_, PgTp_, PgSz_> > stream_type;
00261     };
00262 
00263 
00270     template <class InputIterator_>
00271     class vector_iterator2stream_sr
00272     {
00273         vector_iterator2stream<InputIterator_> * vec_it_stream;
00274         iterator2stream<InputIterator_> * it_stream;
00275 
00276         typedef typename InputIterator_::block_type block_type;
00277 
00278     public:
00279         typedef vector_iterator2stream_sr<InputIterator_> Self_;
00280 
00282         typedef typename std::iterator_traits<InputIterator_>::value_type value_type;
00283 
00284         vector_iterator2stream_sr(InputIterator_ begin, InputIterator_ end, unsigned_type nbuffers = 0)
00285         {
00286             if (end - begin < block_type::size)
00287             {
00288                 STXXL_VERBOSE1("vector_iterator2stream_sr::vector_iterator2stream_sr: Choosing iterator2stream<InputIterator_>");
00289                 it_stream = new iterator2stream<InputIterator_>(begin, end);
00290                 vec_it_stream = NULL;
00291             }
00292             else
00293             {
00294                 STXXL_VERBOSE1("vector_iterator2stream_sr::vector_iterator2stream_sr: Choosing vector_iterator2stream<InputIterator_>");
00295                 it_stream = NULL;
00296                 vec_it_stream = new vector_iterator2stream<InputIterator_>(begin, end, nbuffers);
00297             }
00298         }
00299 
00300         vector_iterator2stream_sr(const Self_ & a) : vec_it_stream(a.vec_it_stream), it_stream(a.it_stream) { }
00301 
00303         const value_type & operator * () const
00304         {
00305             if (it_stream)
00306                 return **it_stream;
00307 
00308             return **vec_it_stream;
00309         }
00310 
00311         const value_type * operator -> () const
00312         {
00313             if (it_stream)
00314                 return &(**it_stream);
00315 
00316             return &(**vec_it_stream);
00317         }
00318 
00320         Self_ & operator ++ ()
00321         {
00322             if (it_stream)
00323                 ++(*it_stream);
00324 
00325             else
00326                 ++(*vec_it_stream);
00327 
00328 
00329             return *this;
00330         }
00331 
00333         bool empty() const
00334         {
00335             if (it_stream)
00336                 return it_stream->empty();
00337 
00338             return vec_it_stream->empty();
00339         }
00340         virtual ~vector_iterator2stream_sr()
00341         {
00342             if (it_stream)
00343                 delete it_stream;
00344 
00345             else
00346                 delete vec_it_stream;
00347         }
00348     };
00349 
00351     template <typename Tp_, typename AllocStr_, typename SzTp_, typename DiffTp_,
00352               unsigned BlkSize_, typename PgTp_, unsigned PgSz_>
00353     vector_iterator2stream_sr<stxxl::vector_iterator<Tp_, AllocStr_, SzTp_, DiffTp_, BlkSize_, PgTp_, PgSz_> >
00354     streamify_sr(
00355         stxxl::vector_iterator<Tp_, AllocStr_, SzTp_, DiffTp_, BlkSize_, PgTp_, PgSz_> begin,
00356         stxxl::vector_iterator<Tp_, AllocStr_, SzTp_, DiffTp_, BlkSize_, PgTp_, PgSz_> end,
00357         unsigned_type nbuffers = 0)
00358     {
00359         STXXL_VERBOSE1("streamify_sr for vector_iterator range is called");
00360         return vector_iterator2stream_sr<stxxl::vector_iterator<Tp_, AllocStr_, SzTp_, DiffTp_, BlkSize_, PgTp_, PgSz_> >
00361                    (begin, end, nbuffers);
00362     }
00363 
00365     template <typename Tp_, typename AllocStr_, typename SzTp_, typename DiffTp_,
00366               unsigned BlkSize_, typename PgTp_, unsigned PgSz_>
00367     vector_iterator2stream_sr<stxxl::const_vector_iterator<Tp_, AllocStr_, SzTp_, DiffTp_, BlkSize_, PgTp_, PgSz_> >
00368     streamify_sr(
00369         stxxl::const_vector_iterator<Tp_, AllocStr_, SzTp_, DiffTp_, BlkSize_, PgTp_, PgSz_> begin,
00370         stxxl::const_vector_iterator<Tp_, AllocStr_, SzTp_, DiffTp_, BlkSize_, PgTp_, PgSz_> end,
00371         unsigned_type nbuffers = 0)
00372     {
00373         STXXL_VERBOSE1("streamify_sr for const_vector_iterator range is called");
00374         return vector_iterator2stream_sr<stxxl::const_vector_iterator<Tp_, AllocStr_, SzTp_, DiffTp_, BlkSize_, PgTp_, PgSz_> >
00375                    (begin, end, nbuffers);
00376     }
00377 
00378 
00380     //     MATERIALIZE                                                    //
00382 
00389     template <class OutputIterator_, class StreamAlgorithm_>
00390     OutputIterator_ materialize(StreamAlgorithm_ & in, OutputIterator_ out)
00391     {
00392         STXXL_VERBOSE_MATERIALIZE(STXXL_PRETTY_FUNCTION_NAME);
00393         while (!in.empty())
00394         {
00395             *out = *in;
00396             ++out;
00397             ++in;
00398         }
00399         return out;
00400     }
00401 
00402 
00412     template <class OutputIterator_, class StreamAlgorithm_>
00413     OutputIterator_ materialize(StreamAlgorithm_ & in, OutputIterator_ outbegin, OutputIterator_ outend)
00414     {
00415         STXXL_VERBOSE_MATERIALIZE(STXXL_PRETTY_FUNCTION_NAME);
00416         while ((!in.empty()) && outend != outbegin)
00417         {
00418             *outbegin = *in;
00419             ++outbegin;
00420             ++in;
00421         }
00422         return outbegin;
00423     }
00424 
00425 
00437     template <typename Tp_, typename AllocStr_, typename SzTp_, typename DiffTp_,
00438               unsigned BlkSize_, typename PgTp_, unsigned PgSz_, class StreamAlgorithm_>
00439     stxxl::vector_iterator<Tp_, AllocStr_, SzTp_, DiffTp_, BlkSize_, PgTp_, PgSz_>
00440     materialize(StreamAlgorithm_ & in,
00441                 stxxl::vector_iterator<Tp_, AllocStr_, SzTp_, DiffTp_, BlkSize_, PgTp_, PgSz_> outbegin,
00442                 stxxl::vector_iterator<Tp_, AllocStr_, SzTp_, DiffTp_, BlkSize_, PgTp_, PgSz_> outend,
00443                 unsigned_type nbuffers = 0)
00444     {
00445         STXXL_VERBOSE_MATERIALIZE(STXXL_PRETTY_FUNCTION_NAME);
00446         typedef stxxl::vector_iterator<Tp_, AllocStr_, SzTp_, DiffTp_, BlkSize_, PgTp_, PgSz_> ExtIterator;
00447         typedef stxxl::const_vector_iterator<Tp_, AllocStr_, SzTp_, DiffTp_, BlkSize_, PgTp_, PgSz_> ConstExtIterator;
00448         typedef buf_ostream<typename ExtIterator::block_type, typename ExtIterator::bids_container_iterator> buf_ostream_type;
00449 
00450 
00451         while (outbegin.block_offset()) //  go to the beginning of the block
00452         //  of the external vector
00453         {
00454             if (in.empty() || outbegin == outend)
00455                 return outbegin;
00456 
00457             *outbegin = *in;
00458             ++outbegin;
00459             ++in;
00460         }
00461 
00462         if (nbuffers == 0)
00463             nbuffers = 2 * config::get_instance()->disks_number();
00464 
00465         outbegin.flush(); // flush container
00466 
00467         // create buffered write stream for blocks
00468         buf_ostream_type outstream(outbegin.bid(), nbuffers);
00469 
00470         assert(outbegin.block_offset() == 0);
00471 
00472         // delay calling block_externally_updated() until the block is
00473         // completely filled (and written out) in outstream
00474         ConstExtIterator prev_block = outbegin;
00475 
00476         while (!in.empty() && outend != outbegin)
00477         {
00478             if (outbegin.block_offset() == 0) {
00479                 if (prev_block != outbegin) {
00480                     prev_block.block_externally_updated();
00481                     prev_block = outbegin;
00482                 }
00483             }
00484 
00485             *outstream = *in;
00486             ++outbegin;
00487             ++outstream;
00488             ++in;
00489         }
00490 
00491         ConstExtIterator const_out = outbegin;
00492 
00493         while (const_out.block_offset()) // filling the rest of the block
00494         {
00495             *outstream = *const_out;
00496             ++const_out;
00497             ++outstream;
00498         }
00499 
00500         if (prev_block != outbegin)
00501             prev_block.block_externally_updated();
00502 
00503         outbegin.flush();
00504 
00505         return outbegin;
00506     }
00507 
00508 
00517     template <typename Tp_, typename AllocStr_, typename SzTp_, typename DiffTp_,
00518               unsigned BlkSize_, typename PgTp_, unsigned PgSz_, class StreamAlgorithm_>
00519     stxxl::vector_iterator<Tp_, AllocStr_, SzTp_, DiffTp_, BlkSize_, PgTp_, PgSz_>
00520     materialize(StreamAlgorithm_ & in,
00521                 stxxl::vector_iterator<Tp_, AllocStr_, SzTp_, DiffTp_, BlkSize_, PgTp_, PgSz_> out,
00522                 unsigned_type nbuffers = 0)
00523     {
00524         STXXL_VERBOSE_MATERIALIZE(STXXL_PRETTY_FUNCTION_NAME);
00525         typedef stxxl::vector_iterator<Tp_, AllocStr_, SzTp_, DiffTp_, BlkSize_, PgTp_, PgSz_> ExtIterator;
00526         typedef stxxl::const_vector_iterator<Tp_, AllocStr_, SzTp_, DiffTp_, BlkSize_, PgTp_, PgSz_> ConstExtIterator;
00527         typedef buf_ostream<typename ExtIterator::block_type, typename ExtIterator::bids_container_iterator> buf_ostream_type;
00528 
00529         // on the I/O complexity of "materialize":
00530         // crossing block boundary causes O(1) I/Os
00531         // if you stay in a block, then materialize function accesses only the cache of the
00532         // vector (only one block indeed), amortized complexity should apply here
00533 
00534         while (out.block_offset()) //  go to the beginning of the block
00535         //  of the external vector
00536         {
00537             if (in.empty())
00538                 return out;
00539 
00540             *out = *in;
00541             ++out;
00542             ++in;
00543         }
00544 
00545         if (nbuffers == 0)
00546             nbuffers = 2 * config::get_instance()->disks_number();
00547 
00548 
00549         out.flush(); // flush container
00550 
00551         // create buffered write stream for blocks
00552         buf_ostream_type outstream(out.bid(), nbuffers);
00553 
00554         assert(out.block_offset() == 0);
00555 
00556         // delay calling block_externally_updated() until the block is
00557         // completely filled (and written out) in outstream
00558         ConstExtIterator prev_block = out;
00559 
00560         while (!in.empty())
00561         {
00562             if (out.block_offset() == 0) {
00563                 if (prev_block != out) {
00564                     prev_block.block_externally_updated();
00565                     prev_block = out;
00566                 }
00567             }
00568 
00569             // tells the vector that the block was modified
00570             *outstream = *in;
00571             ++out;
00572             ++outstream;
00573             ++in;
00574         }
00575 
00576         ConstExtIterator const_out = out;
00577 
00578         while (const_out.block_offset())
00579         {
00580             *outstream = *const_out;             // might cause I/Os for loading the page that
00581             ++const_out;                         // contains data beyond out
00582             ++outstream;
00583         }
00584 
00585         if (prev_block != out)
00586             prev_block.block_externally_updated();
00587 
00588         out.flush();
00589 
00590         return out;
00591     }
00592 
00593 
00595     //     GENERATE                                                       //
00597 
00601     template <class Generator_, typename T = typename Generator_::value_type>
00602     class generator2stream
00603     {
00604     public:
00606         typedef T value_type;
00607 
00608     private:
00609         Generator_ gen_;
00610         value_type current_;
00611 
00612     public:
00613         generator2stream(Generator_ g) :
00614             gen_(g), current_(gen_()) { }
00615 
00616         generator2stream(const generator2stream & a) : gen_(a.gen_), current_(a.current_) { }
00617 
00619         const value_type & operator * () const
00620         {
00621             return current_;
00622         }
00623 
00624         const value_type * operator -> () const
00625         {
00626             return &current_;
00627         }
00628 
00630         generator2stream & operator ++ ()
00631         {
00632             current_ = gen_();
00633             return *this;
00634         }
00635 
00637         bool empty() const
00638         {
00639             return false;
00640         }
00641     };
00642 
00646     template <class Generator_>
00647     generator2stream<Generator_> streamify(Generator_ gen_)
00648     {
00649         return generator2stream<Generator_>(gen_);
00650     }
00651 
00652 
00654     //     TRANSFORM                                                      //
00656 
00657     struct Stopper { };
00658 
00670     template <class Operation_,
00671               class Input1_,
00672               class Input2_ = Stopper,
00673               class Input3_ = Stopper,
00674               class Input4_ = Stopper,
00675               class Input5_ = Stopper,
00676               class Input6_ = Stopper
00677               >
00678     class transform
00679     {
00680         Operation_ & op;
00681         Input1_ & i1;
00682         Input2_ & i2;
00683         Input3_ & i3;
00684         Input4_ & i4;
00685         Input5_ & i5;
00686         Input6_ & i6;
00687 
00688     public:
00690         typedef typename Operation_::value_type value_type;
00691 
00692     private:
00693         value_type current;
00694 
00695     public:
00697         transform(Operation_ & o, Input1_ & i1_, Input2_ & i2_, Input3_ & i3_, Input4_ & i4_,
00698                   Input5_ & i5_, Input5_ & i6_) :
00699             op(o), i1(i1_), i2(i2_), i3(i3_), i4(i4_), i5(i5_), i6(i6_)
00700         {
00701             if (!empty())
00702                 current = op(*i1, *i2, *i3, *i4, *i5, *i6);
00703         }
00704 
00706         const value_type & operator * () const
00707         {
00708             return current;
00709         }
00710 
00711         const value_type * operator -> () const
00712         {
00713             return &current;
00714         }
00715 
00717         transform & operator ++ ()
00718         {
00719             ++i1;
00720             ++i2;
00721             ++i3;
00722             ++i4;
00723             ++i5;
00724             ++i6;
00725             if (!empty())
00726                 current = op(*i1, *i2, *i3, *i4, *i5, *i6);
00727 
00728             return *this;
00729         }
00730 
00732         bool empty() const
00733         {
00734             return i1.empty() || i2.empty() || i3.empty() ||
00735                    i4.empty() || i5.empty() || i6.empty();
00736         }
00737     };
00738 
00739     // Specializations
00740 
00742     //     TRANSFORM (1 input stream)                                     //
00744 
00752     template <class Operation_,
00753               class Input1_
00754               >
00755     class transform<Operation_, Input1_, Stopper, Stopper, Stopper, Stopper, Stopper>
00756     {
00757         Operation_ & op;
00758         Input1_ & i1;
00759 
00760     public:
00762         typedef typename Operation_::value_type value_type;
00763 
00764     private:
00765         value_type current;
00766 
00767     public:
00769         transform(Operation_ & o, Input1_ & i1_) : op(o), i1(i1_)
00770         {
00771             if (!empty())
00772                 current = op(*i1);
00773         }
00774 
00776         const value_type & operator * () const
00777         {
00778             return current;
00779         }
00780 
00781         const value_type * operator -> () const
00782         {
00783             return &current;
00784         }
00785 
00787         transform & operator ++ ()
00788         {
00789             ++i1;
00790             if (!empty())
00791                 current = op(*i1);
00792 
00793             return *this;
00794         }
00795 
00797         bool empty() const
00798         {
00799             return i1.empty();
00800         }
00801     };
00802 
00803 
00805     //     TRANSFORM (2 input streams)                                    //
00807 
00816     template <class Operation_,
00817               class Input1_,
00818               class Input2_
00819               >
00820     class transform<Operation_, Input1_, Input2_, Stopper, Stopper, Stopper, Stopper>
00821     {
00822         Operation_ & op;
00823         Input1_ & i1;
00824         Input2_ & i2;
00825 
00826     public:
00828         typedef typename Operation_::value_type value_type;
00829 
00830     private:
00831         value_type current;
00832 
00833     public:
00835         transform(Operation_ & o, Input1_ & i1_, Input2_ & i2_) : op(o), i1(i1_), i2(i2_)
00836         {
00837             if (!empty())
00838                 current = op(*i1, *i2);
00839         }
00840 
00842         const value_type & operator * () const
00843         {
00844             return current;
00845         }
00846 
00847         const value_type * operator -> () const
00848         {
00849             return &current;
00850         }
00851 
00853         transform & operator ++ ()
00854         {
00855             ++i1;
00856             ++i2;
00857             if (!empty())
00858                 current = op(*i1, *i2);
00859 
00860             return *this;
00861         }
00862 
00864         bool empty() const
00865         {
00866             return i1.empty() || i2.empty();
00867         }
00868     };
00869 
00870 
00872     //     TRANSFORM (3 input streams)                                    //
00874 
00884     template <class Operation_,
00885               class Input1_,
00886               class Input2_,
00887               class Input3_
00888               >
00889     class transform<Operation_, Input1_, Input2_, Input3_, Stopper, Stopper, Stopper>
00890     {
00891         Operation_ & op;
00892         Input1_ & i1;
00893         Input2_ & i2;
00894         Input3_ & i3;
00895 
00896     public:
00898         typedef typename Operation_::value_type value_type;
00899 
00900     private:
00901         value_type current;
00902 
00903     public:
00905         transform(Operation_ & o, Input1_ & i1_, Input2_ & i2_, Input3_ & i3_) :
00906             op(o), i1(i1_), i2(i2_), i3(i3_)
00907         {
00908             if (!empty())
00909                 current = op(*i1, *i2, *i3);
00910         }
00911 
00913         const value_type & operator * () const
00914         {
00915             return current;
00916         }
00917 
00918         const value_type * operator -> () const
00919         {
00920             return &current;
00921         }
00922 
00924         transform & operator ++ ()
00925         {
00926             ++i1;
00927             ++i2;
00928             ++i3;
00929             if (!empty())
00930                 current = op(*i1, *i2, *i3);
00931 
00932             return *this;
00933         }
00934 
00936         bool empty() const
00937         {
00938             return i1.empty() || i2.empty() || i3.empty();
00939         }
00940     };
00941 
00942 
00944     //     TRANSFORM (4 input streams)                                    //
00946 
00957     template <class Operation_,
00958               class Input1_,
00959               class Input2_,
00960               class Input3_,
00961               class Input4_
00962               >
00963     class transform<Operation_, Input1_, Input2_, Input3_, Input4_, Stopper, Stopper>
00964     {
00965         Operation_ & op;
00966         Input1_ & i1;
00967         Input2_ & i2;
00968         Input3_ & i3;
00969         Input4_ & i4;
00970 
00971     public:
00973         typedef typename Operation_::value_type value_type;
00974 
00975     private:
00976         value_type current;
00977 
00978     public:
00980         transform(Operation_ & o, Input1_ & i1_, Input2_ & i2_, Input3_ & i3_, Input4_ & i4_) :
00981             op(o), i1(i1_), i2(i2_), i3(i3_), i4(i4_)
00982         {
00983             if (!empty())
00984                 current = op(*i1, *i2, *i3, *i4);
00985         }
00986 
00988         const value_type & operator * () const
00989         {
00990             return current;
00991         }
00992 
00993         const value_type * operator -> () const
00994         {
00995             return &current;
00996         }
00997 
00999         transform & operator ++ ()
01000         {
01001             ++i1;
01002             ++i2;
01003             ++i3;
01004             ++i4;
01005             if (!empty())
01006                 current = op(*i1, *i2, *i3, *i4);
01007 
01008             return *this;
01009         }
01010 
01012         bool empty() const
01013         {
01014             return i1.empty() || i2.empty() || i3.empty() || i4.empty();
01015         }
01016     };
01017 
01018 
01020     //     TRANSFORM (5 input streams)                                    //
01022 
01034     template <class Operation_,
01035               class Input1_,
01036               class Input2_,
01037               class Input3_,
01038               class Input4_,
01039               class Input5_
01040               >
01041     class transform<Operation_, Input1_, Input2_, Input3_, Input4_, Input5_, Stopper>
01042     {
01043         Operation_ & op;
01044         Input1_ & i1;
01045         Input2_ & i2;
01046         Input3_ & i3;
01047         Input4_ & i4;
01048         Input5_ & i5;
01049 
01050     public:
01052         typedef typename Operation_::value_type value_type;
01053 
01054     private:
01055         value_type current;
01056 
01057     public:
01059         transform(Operation_ & o, Input1_ & i1_, Input2_ & i2_, Input3_ & i3_, Input4_ & i4_,
01060                   Input5_ & i5_) :
01061             op(o), i1(i1_), i2(i2_), i3(i3_), i4(i4_), i5(i5_)
01062         {
01063             if (!empty())
01064                 current = op(*i1, *i2, *i3, *i4, *i5);
01065         }
01066 
01068         const value_type & operator * () const
01069         {
01070             return current;
01071         }
01072 
01073         const value_type * operator -> () const
01074         {
01075             return &current;
01076         }
01077 
01079         transform & operator ++ ()
01080         {
01081             ++i1;
01082             ++i2;
01083             ++i3;
01084             ++i4;
01085             ++i5;
01086             if (!empty())
01087                 current = op(*i1, *i2, *i3, *i4, *i5);
01088 
01089             return *this;
01090         }
01091 
01093         bool empty() const
01094         {
01095             return i1.empty() || i2.empty() || i3.empty() || i4.empty() || i5.empty();
01096         }
01097     };
01098 
01099 
01101     //     MAKE TUPLE                                                     //
01103 
01113     template <class Input1_,
01114               class Input2_,
01115               class Input3_ = Stopper,
01116               class Input4_ = Stopper,
01117               class Input5_ = Stopper,
01118               class Input6_ = Stopper
01119               >
01120     class make_tuple
01121     {
01122         Input1_ & i1;
01123         Input2_ & i2;
01124         Input3_ & i3;
01125         Input4_ & i4;
01126         Input5_ & i5;
01127         Input6_ & i6;
01128 
01129     public:
01131         typedef typename stxxl::tuple<
01132             typename Input1_::value_type,
01133             typename Input2_::value_type,
01134             typename Input3_::value_type,
01135             typename Input4_::value_type,
01136             typename Input5_::value_type,
01137             typename Input6_::value_type
01138             > value_type;
01139 
01140     private:
01141         value_type current;
01142 
01143     public:
01145         make_tuple(
01146             Input1_ & i1_,
01147             Input2_ & i2_,
01148             Input3_ & i3_,
01149             Input4_ & i4_,
01150             Input5_ & i5_,
01151             Input6_ & i6_
01152             ) :
01153             i1(i1_), i2(i2_), i3(i3_), i4(i4_), i5(i5_), i6(i6_),
01154             current(value_type(*i1, *i2, *i3, *i4, *i5, *i6)) { }
01155 
01157         const value_type & operator * () const
01158         {
01159             return current;
01160         }
01161 
01162         const value_type * operator -> () const
01163         {
01164             return &current;
01165         }
01166 
01168         make_tuple & operator ++ ()
01169         {
01170             ++i1;
01171             ++i2;
01172             ++i3;
01173             ++i4;
01174             ++i5;
01175             ++i6;
01176 
01177             if (!empty())
01178                 current = value_type(*i1, *i2, *i3, *i4, *i5, *i6);
01179 
01180             return *this;
01181         }
01182 
01184         bool empty() const
01185         {
01186             return i1.empty() || i2.empty() || i3.empty() ||
01187                    i4.empty() || i5.empty() || i6.empty();
01188         }
01189     };
01190 
01191 
01198     template <class Input1_,
01199               class Input2_
01200               >
01201     class make_tuple<Input1_, Input2_, Stopper, Stopper, Stopper, Stopper>
01202     {
01203         Input1_ & i1;
01204         Input2_ & i2;
01205 
01206     public:
01208         typedef typename stxxl::tuple<
01209             typename Input1_::value_type,
01210             typename Input2_::value_type
01211             > value_type;
01212 
01213     private:
01214         value_type current;
01215 
01216     public:
01218         make_tuple(
01219             Input1_ & i1_,
01220             Input2_ & i2_
01221             ) :
01222             i1(i1_), i2(i2_)
01223         {
01224             if (!empty())
01225             {
01226                 current = value_type(*i1, *i2);
01227             }
01228         }
01229 
01231         const value_type & operator * () const
01232         {
01233             return current;
01234         }
01235 
01236         const value_type * operator -> () const
01237         {
01238             return &current;
01239         }
01240 
01242         make_tuple & operator ++ ()
01243         {
01244             ++i1;
01245             ++i2;
01246 
01247             if (!empty())
01248                 current = value_type(*i1, *i2);
01249 
01250             return *this;
01251         }
01252 
01254         bool empty() const
01255         {
01256             return i1.empty() || i2.empty();
01257         }
01258     };
01259 
01267     template <class Input1_,
01268               class Input2_,
01269               class Input3_
01270               >
01271     class make_tuple<Input1_, Input2_, Input3_, Stopper, Stopper, Stopper>
01272     {
01273         Input1_ & i1;
01274         Input2_ & i2;
01275         Input3_ & i3;
01276 
01277     public:
01279         typedef typename stxxl::tuple<
01280             typename Input1_::value_type,
01281             typename Input2_::value_type,
01282             typename Input3_::value_type
01283             > value_type;
01284 
01285     private:
01286         value_type current;
01287 
01288     public:
01290         make_tuple(
01291             Input1_ & i1_,
01292             Input2_ & i2_,
01293             Input3_ & i3_
01294             ) :
01295             i1(i1_), i2(i2_), i3(i3_),
01296             current(value_type(*i1, *i2, *i3)) { }
01297 
01299         const value_type & operator * () const
01300         {
01301             return current;
01302         }
01303 
01304         const value_type * operator -> () const
01305         {
01306             return &current;
01307         }
01308 
01310         make_tuple & operator ++ ()
01311         {
01312             ++i1;
01313             ++i2;
01314             ++i3;
01315 
01316             if (!empty())
01317                 current = value_type(*i1, *i2, *i3);
01318 
01319             return *this;
01320         }
01321 
01323         bool empty() const
01324         {
01325             return i1.empty() || i2.empty() || i3.empty();
01326         }
01327     };
01328 
01337     template <class Input1_,
01338               class Input2_,
01339               class Input3_,
01340               class Input4_
01341               >
01342     class make_tuple<Input1_, Input2_, Input3_, Input4_, Stopper, Stopper>
01343     {
01344         Input1_ & i1;
01345         Input2_ & i2;
01346         Input3_ & i3;
01347         Input4_ & i4;
01348 
01349     public:
01351         typedef typename stxxl::tuple<
01352             typename Input1_::value_type,
01353             typename Input2_::value_type,
01354             typename Input3_::value_type,
01355             typename Input4_::value_type
01356             > value_type;
01357 
01358     private:
01359         value_type current;
01360 
01361     public:
01363         make_tuple(
01364             Input1_ & i1_,
01365             Input2_ & i2_,
01366             Input3_ & i3_,
01367             Input4_ & i4_
01368             ) :
01369             i1(i1_), i2(i2_), i3(i3_), i4(i4_),
01370             current(value_type(*i1, *i2, *i3, *i4)) { }
01371 
01373         const value_type & operator * () const
01374         {
01375             return current;
01376         }
01377 
01378         const value_type * operator -> () const
01379         {
01380             return &current;
01381         }
01382 
01384         make_tuple & operator ++ ()
01385         {
01386             ++i1;
01387             ++i2;
01388             ++i3;
01389             ++i4;
01390 
01391             if (!empty())
01392                 current = value_type(*i1, *i2, *i3, *i4);
01393 
01394             return *this;
01395         }
01396 
01398         bool empty() const
01399         {
01400             return i1.empty() || i2.empty() || i3.empty() ||
01401                    i4.empty();
01402         }
01403     };
01404 
01414     template <
01415         class Input1_,
01416         class Input2_,
01417         class Input3_,
01418         class Input4_,
01419         class Input5_
01420         >
01421     class make_tuple<Input1_, Input2_, Input3_, Input4_, Input5_, Stopper>
01422     {
01423         Input1_ & i1;
01424         Input2_ & i2;
01425         Input3_ & i3;
01426         Input4_ & i4;
01427         Input5_ & i5;
01428 
01429     public:
01431         typedef typename stxxl::tuple<
01432             typename Input1_::value_type,
01433             typename Input2_::value_type,
01434             typename Input3_::value_type,
01435             typename Input4_::value_type,
01436             typename Input5_::value_type
01437             > value_type;
01438 
01439     private:
01440         value_type current;
01441 
01442     public:
01444         make_tuple(
01445             Input1_ & i1_,
01446             Input2_ & i2_,
01447             Input3_ & i3_,
01448             Input4_ & i4_,
01449             Input5_ & i5_
01450             ) :
01451             i1(i1_), i2(i2_), i3(i3_), i4(i4_), i5(i5_),
01452             current(value_type(*i1, *i2, *i3, *i4, *i5)) { }
01453 
01455         const value_type & operator * () const
01456         {
01457             return current;
01458         }
01459 
01460         const value_type * operator -> () const
01461         {
01462             return &current;
01463         }
01464 
01466         make_tuple & operator ++ ()
01467         {
01468             ++i1;
01469             ++i2;
01470             ++i3;
01471             ++i4;
01472             ++i5;
01473 
01474             if (!empty())
01475                 current = value_type(*i1, *i2, *i3, *i4, *i5);
01476 
01477             return *this;
01478         }
01479 
01481         bool empty() const
01482         {
01483             return i1.empty() || i2.empty() || i3.empty() ||
01484                    i4.empty() || i5.empty();
01485         }
01486     };
01487 
01488 
01490 }
01491 
01492 __STXXL_END_NAMESPACE
01493 
01494 
01495 #include <stxxl/bits/stream/choose.h>
01496 #include <stxxl/bits/stream/unique.h>
01497 
01498 
01499 #endif // !STXXL_STREAM_HEADER
01500 // vim: et:ts=4:sw=4

Generated by  doxygen 1.7.1