• 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  *  Copyright (C) 2009, 2010 Andreas Beckmann <[email protected]>
00008  *  Copyright (C) 2010 Johannes Singler <[email protected]>
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 
00034 namespace stream
00035 {
00060 
00061 
00063     //     STREAMIFY                                                      //
00065 
00069     template <class InputIterator_>
00070     class iterator2stream
00071     {
00072         InputIterator_ current_, end_;
00073 
00074     public:
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 
00084         const value_type & operator * () const
00085         {
00086             return *current_;
00087         }
00088 
00089         const value_type * operator -> () const
00090         {
00091             return &(*current_);
00092         }
00093 
00095         iterator2stream & operator ++ ()
00096         {
00097             assert(end_ != current_);
00098             ++current_;
00099             return *this;
00100         }
00101 
00103         bool empty() const
00104         {
00105             return (current_ == end_);
00106         }
00107     };
00108 
00109 
00114     template <class InputIterator_>
00115     iterator2stream<InputIterator_> streamify(InputIterator_ begin, InputIterator_ end)
00116     {
00117         return iterator2stream<InputIterator_>(begin, end);
00118     }
00119 
00121     template <class InputIterator_>
00122     struct streamify_traits
00123     {
00125         typedef iterator2stream<InputIterator_> stream_type;
00126     };
00127 
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 
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             begin.flush();     // flush container
00157             typename InputIterator_::bids_container_iterator end_iter = end.bid() + ((end.block_offset()) ? 1 : 0);
00158 
00159             if (end_iter - begin.bid() > 0)
00160             {
00161                 in.reset(new buf_istream_type(begin.bid(), end_iter, nbuffers ? nbuffers :
00162                                               (2 * config::get_instance()->disks_number())));
00163 
00164                 InputIterator_ cur = begin - begin.block_offset();
00165 
00166                 // skip the beginning of the block
00167                 for ( ; cur != begin; ++cur)
00168                     ++(*in);
00169             }
00170         }
00171 
00172         vector_iterator2stream(const Self_ & a) :
00173             current_(a.current_), end_(a.end_), in(a.in.release()) { }
00174 
00176         const value_type & operator * () const
00177         {
00178             return **in;
00179         }
00180 
00181         const value_type * operator -> () const
00182         {
00183             return &(**in);
00184         }
00185 
00187         Self_ & operator ++ ()
00188         {
00189             assert(end_ != current_);
00190             ++current_;
00191             ++(*in);
00192             if (empty())
00193                 delete_stream();
00194 
00195             return *this;
00196         }
00197 
00199         bool empty() const
00200         {
00201             return (current_ == end_);
00202         }
00203         virtual ~vector_iterator2stream()
00204         {
00205             delete_stream();      // not needed actually
00206         }
00207     };
00208 
00216 
00217     template <typename Tp_, typename AllocStr_, typename SzTp_, typename DiffTp_,
00218               unsigned BlkSize_, typename PgTp_, unsigned PgSz_>
00219     vector_iterator2stream<stxxl::vector_iterator<Tp_, AllocStr_, SzTp_, DiffTp_, BlkSize_, PgTp_, PgSz_> >
00220     streamify(
00221         stxxl::vector_iterator<Tp_, AllocStr_, SzTp_, DiffTp_, BlkSize_, PgTp_, PgSz_> begin,
00222         stxxl::vector_iterator<Tp_, AllocStr_, SzTp_, DiffTp_, BlkSize_, PgTp_, PgSz_> end,
00223         unsigned_type nbuffers = 0)
00224     {
00225         STXXL_VERBOSE1("streamify for vector_iterator range is called");
00226         return vector_iterator2stream<stxxl::vector_iterator<Tp_, AllocStr_, SzTp_, DiffTp_, BlkSize_, PgTp_, PgSz_> >
00227                    (begin, end, nbuffers);
00228     }
00229 
00230     template <typename Tp_, typename AllocStr_, typename SzTp_, typename DiffTp_,
00231               unsigned BlkSize_, typename PgTp_, unsigned PgSz_>
00232     struct streamify_traits<stxxl::vector_iterator<Tp_, AllocStr_, SzTp_, DiffTp_, BlkSize_, PgTp_, PgSz_> >
00233     {
00234         typedef vector_iterator2stream<stxxl::vector_iterator<Tp_, AllocStr_, SzTp_, DiffTp_, BlkSize_, PgTp_, PgSz_> > stream_type;
00235     };
00236 
00244 
00245     template <typename Tp_, typename AllocStr_, typename SzTp_, typename DiffTp_,
00246               unsigned BlkSize_, typename PgTp_, unsigned PgSz_>
00247     vector_iterator2stream<stxxl::const_vector_iterator<Tp_, AllocStr_, SzTp_, DiffTp_, BlkSize_, PgTp_, PgSz_> >
00248     streamify(
00249         stxxl::const_vector_iterator<Tp_, AllocStr_, SzTp_, DiffTp_, BlkSize_, PgTp_, PgSz_> begin,
00250         stxxl::const_vector_iterator<Tp_, AllocStr_, SzTp_, DiffTp_, BlkSize_, PgTp_, PgSz_> end,
00251         unsigned_type nbuffers = 0)
00252     {
00253         STXXL_VERBOSE1("streamify for const_vector_iterator range is called");
00254         return vector_iterator2stream<stxxl::const_vector_iterator<Tp_, AllocStr_, SzTp_, DiffTp_, BlkSize_, PgTp_, PgSz_> >
00255                    (begin, end, nbuffers);
00256     }
00257 
00258     template <typename Tp_, typename AllocStr_, typename SzTp_, typename DiffTp_,
00259               unsigned BlkSize_, typename PgTp_, unsigned PgSz_>
00260     struct streamify_traits<stxxl::const_vector_iterator<Tp_, AllocStr_, SzTp_, DiffTp_, BlkSize_, PgTp_, PgSz_> >
00261     {
00262         typedef vector_iterator2stream<stxxl::const_vector_iterator<Tp_, AllocStr_, SzTp_, DiffTp_, BlkSize_, PgTp_, PgSz_> > stream_type;
00263     };
00264 
00265 
00272     template <class InputIterator_>
00273     class vector_iterator2stream_sr
00274     {
00275         vector_iterator2stream<InputIterator_> * vec_it_stream;
00276         iterator2stream<InputIterator_> * it_stream;
00277 
00278         typedef typename InputIterator_::block_type block_type;
00279 
00280     public:
00281         typedef vector_iterator2stream_sr<InputIterator_> Self_;
00282 
00284         typedef typename std::iterator_traits<InputIterator_>::value_type value_type;
00285 
00286         vector_iterator2stream_sr(InputIterator_ begin, InputIterator_ end, unsigned_type nbuffers = 0)
00287         {
00288             if (end - begin < block_type::size)
00289             {
00290                 STXXL_VERBOSE1("vector_iterator2stream_sr::vector_iterator2stream_sr: Choosing iterator2stream<InputIterator_>");
00291                 it_stream = new iterator2stream<InputIterator_>(begin, end);
00292                 vec_it_stream = NULL;
00293             }
00294             else
00295             {
00296                 STXXL_VERBOSE1("vector_iterator2stream_sr::vector_iterator2stream_sr: Choosing vector_iterator2stream<InputIterator_>");
00297                 it_stream = NULL;
00298                 vec_it_stream = new vector_iterator2stream<InputIterator_>(begin, end, nbuffers);
00299             }
00300         }
00301 
00302         vector_iterator2stream_sr(const Self_ & a) : vec_it_stream(a.vec_it_stream), it_stream(a.it_stream) { }
00303 
00305         const value_type & operator * () const
00306         {
00307             if (it_stream)
00308                 return **it_stream;
00309 
00310             return **vec_it_stream;
00311         }
00312 
00313         const value_type * operator -> () const
00314         {
00315             if (it_stream)
00316                 return &(**it_stream);
00317 
00318             return &(**vec_it_stream);
00319         }
00320 
00322         Self_ & operator ++ ()
00323         {
00324             if (it_stream)
00325                 ++(*it_stream);
00326 
00327             else
00328                 ++(*vec_it_stream);
00329 
00330 
00331             return *this;
00332         }
00333 
00335         bool empty() const
00336         {
00337             if (it_stream)
00338                 return it_stream->empty();
00339 
00340             return vec_it_stream->empty();
00341         }
00342         virtual ~vector_iterator2stream_sr()
00343         {
00344             if (it_stream)
00345                 delete it_stream;
00346 
00347             else
00348                 delete vec_it_stream;
00349         }
00350     };
00351 
00353     template <typename Tp_, typename AllocStr_, typename SzTp_, typename DiffTp_,
00354               unsigned BlkSize_, typename PgTp_, unsigned PgSz_>
00355     vector_iterator2stream_sr<stxxl::vector_iterator<Tp_, AllocStr_, SzTp_, DiffTp_, BlkSize_, PgTp_, PgSz_> >
00356     streamify_sr(
00357         stxxl::vector_iterator<Tp_, AllocStr_, SzTp_, DiffTp_, BlkSize_, PgTp_, PgSz_> begin,
00358         stxxl::vector_iterator<Tp_, AllocStr_, SzTp_, DiffTp_, BlkSize_, PgTp_, PgSz_> end,
00359         unsigned_type nbuffers = 0)
00360     {
00361         STXXL_VERBOSE1("streamify_sr for vector_iterator range is called");
00362         return vector_iterator2stream_sr<stxxl::vector_iterator<Tp_, AllocStr_, SzTp_, DiffTp_, BlkSize_, PgTp_, PgSz_> >
00363                    (begin, end, nbuffers);
00364     }
00365 
00367     template <typename Tp_, typename AllocStr_, typename SzTp_, typename DiffTp_,
00368               unsigned BlkSize_, typename PgTp_, unsigned PgSz_>
00369     vector_iterator2stream_sr<stxxl::const_vector_iterator<Tp_, AllocStr_, SzTp_, DiffTp_, BlkSize_, PgTp_, PgSz_> >
00370     streamify_sr(
00371         stxxl::const_vector_iterator<Tp_, AllocStr_, SzTp_, DiffTp_, BlkSize_, PgTp_, PgSz_> begin,
00372         stxxl::const_vector_iterator<Tp_, AllocStr_, SzTp_, DiffTp_, BlkSize_, PgTp_, PgSz_> end,
00373         unsigned_type nbuffers = 0)
00374     {
00375         STXXL_VERBOSE1("streamify_sr for const_vector_iterator range is called");
00376         return vector_iterator2stream_sr<stxxl::const_vector_iterator<Tp_, AllocStr_, SzTp_, DiffTp_, BlkSize_, PgTp_, PgSz_> >
00377                    (begin, end, nbuffers);
00378     }
00379 
00380 
00382     //     MATERIALIZE                                                    //
00384 
00391     template <class OutputIterator_, class StreamAlgorithm_>
00392     OutputIterator_ materialize(StreamAlgorithm_ & in, OutputIterator_ out)
00393     {
00394         STXXL_VERBOSE_MATERIALIZE(STXXL_PRETTY_FUNCTION_NAME);
00395         while (!in.empty())
00396         {
00397             *out = *in;
00398             ++out;
00399             ++in;
00400         }
00401         return out;
00402     }
00403 
00404 
00414     template <class OutputIterator_, class StreamAlgorithm_>
00415     OutputIterator_ materialize(StreamAlgorithm_ & in, OutputIterator_ outbegin, OutputIterator_ outend)
00416     {
00417         STXXL_VERBOSE_MATERIALIZE(STXXL_PRETTY_FUNCTION_NAME);
00418         while ((!in.empty()) && outend != outbegin)
00419         {
00420             *outbegin = *in;
00421             ++outbegin;
00422             ++in;
00423         }
00424         return outbegin;
00425     }
00426 
00427 
00439     template <typename Tp_, typename AllocStr_, typename SzTp_, typename DiffTp_,
00440               unsigned BlkSize_, typename PgTp_, unsigned PgSz_, class StreamAlgorithm_>
00441     stxxl::vector_iterator<Tp_, AllocStr_, SzTp_, DiffTp_, BlkSize_, PgTp_, PgSz_>
00442     materialize(StreamAlgorithm_ & in,
00443                 stxxl::vector_iterator<Tp_, AllocStr_, SzTp_, DiffTp_, BlkSize_, PgTp_, PgSz_> outbegin,
00444                 stxxl::vector_iterator<Tp_, AllocStr_, SzTp_, DiffTp_, BlkSize_, PgTp_, PgSz_> outend,
00445                 unsigned_type nbuffers = 0)
00446     {
00447         STXXL_VERBOSE_MATERIALIZE(STXXL_PRETTY_FUNCTION_NAME);
00448         typedef stxxl::vector_iterator<Tp_, AllocStr_, SzTp_, DiffTp_, BlkSize_, PgTp_, PgSz_> ExtIterator;
00449         typedef stxxl::const_vector_iterator<Tp_, AllocStr_, SzTp_, DiffTp_, BlkSize_, PgTp_, PgSz_> ConstExtIterator;
00450         typedef buf_ostream<typename ExtIterator::block_type, typename ExtIterator::bids_container_iterator> buf_ostream_type;
00451 
00452 
00453         while (outbegin.block_offset()) //  go to the beginning of the block
00454         //  of the external vector
00455         {
00456             if (in.empty() || outbegin == outend)
00457                 return outbegin;
00458 
00459             *outbegin = *in;
00460             ++outbegin;
00461             ++in;
00462         }
00463 
00464         if (nbuffers == 0)
00465             nbuffers = 2 * config::get_instance()->disks_number();
00466 
00467         outbegin.flush(); // flush container
00468 
00469         // create buffered write stream for blocks
00470         buf_ostream_type outstream(outbegin.bid(), nbuffers);
00471 
00472         assert(outbegin.block_offset() == 0);
00473 
00474         // delay calling block_externally_updated() until the block is
00475         // completely filled (and written out) in outstream
00476         ConstExtIterator prev_block = outbegin;
00477 
00478         while (!in.empty() && outend != outbegin)
00479         {
00480             if (outbegin.block_offset() == 0) {
00481                 if (prev_block != outbegin) {
00482                     prev_block.block_externally_updated();
00483                     prev_block = outbegin;
00484                 }
00485             }
00486 
00487             *outstream = *in;
00488             ++outbegin;
00489             ++outstream;
00490             ++in;
00491         }
00492 
00493         ConstExtIterator const_out = outbegin;
00494 
00495         while (const_out.block_offset()) // filling the rest of the block
00496         {
00497             *outstream = *const_out;
00498             ++const_out;
00499             ++outstream;
00500         }
00501 
00502         if (prev_block != outbegin)
00503             prev_block.block_externally_updated();
00504 
00505         outbegin.flush();
00506 
00507         return outbegin;
00508     }
00509 
00510 
00519     template <typename Tp_, typename AllocStr_, typename SzTp_, typename DiffTp_,
00520               unsigned BlkSize_, typename PgTp_, unsigned PgSz_, class StreamAlgorithm_>
00521     stxxl::vector_iterator<Tp_, AllocStr_, SzTp_, DiffTp_, BlkSize_, PgTp_, PgSz_>
00522     materialize(StreamAlgorithm_ & in,
00523                 stxxl::vector_iterator<Tp_, AllocStr_, SzTp_, DiffTp_, BlkSize_, PgTp_, PgSz_> out,
00524                 unsigned_type nbuffers = 0)
00525     {
00526         STXXL_VERBOSE_MATERIALIZE(STXXL_PRETTY_FUNCTION_NAME);
00527         typedef stxxl::vector_iterator<Tp_, AllocStr_, SzTp_, DiffTp_, BlkSize_, PgTp_, PgSz_> ExtIterator;
00528         typedef stxxl::const_vector_iterator<Tp_, AllocStr_, SzTp_, DiffTp_, BlkSize_, PgTp_, PgSz_> ConstExtIterator;
00529         typedef buf_ostream<typename ExtIterator::block_type, typename ExtIterator::bids_container_iterator> buf_ostream_type;
00530 
00531         // on the I/O complexity of "materialize":
00532         // crossing block boundary causes O(1) I/Os
00533         // if you stay in a block, then materialize function accesses only the cache of the
00534         // vector (only one block indeed), amortized complexity should apply here
00535 
00536         while (out.block_offset()) //  go to the beginning of the block
00537         //  of the external vector
00538         {
00539             if (in.empty())
00540                 return out;
00541 
00542             *out = *in;
00543             ++out;
00544             ++in;
00545         }
00546 
00547         if (nbuffers == 0)
00548             nbuffers = 2 * config::get_instance()->disks_number();
00549 
00550 
00551         out.flush(); // flush container
00552 
00553         // create buffered write stream for blocks
00554         buf_ostream_type outstream(out.bid(), nbuffers);
00555 
00556         assert(out.block_offset() == 0);
00557 
00558         // delay calling block_externally_updated() until the block is
00559         // completely filled (and written out) in outstream
00560         ConstExtIterator prev_block = out;
00561 
00562         while (!in.empty())
00563         {
00564             if (out.block_offset() == 0) {
00565                 if (prev_block != out) {
00566                     prev_block.block_externally_updated();
00567                     prev_block = out;
00568                 }
00569             }
00570 
00571             // tells the vector that the block was modified
00572             *outstream = *in;
00573             ++out;
00574             ++outstream;
00575             ++in;
00576         }
00577 
00578         ConstExtIterator const_out = out;
00579 
00580         while (const_out.block_offset())
00581         {
00582             *outstream = *const_out;             // might cause I/Os for loading the page that
00583             ++const_out;                         // contains data beyond out
00584             ++outstream;
00585         }
00586 
00587         if (prev_block != out)
00588             prev_block.block_externally_updated();
00589 
00590         out.flush();
00591 
00592         return out;
00593     }
00594 
00595 
00600     template <class StreamAlgorithm_>
00601     void discard(StreamAlgorithm_ & in)
00602     {
00603         while (!in.empty())
00604         {
00605             *in;
00606             ++in;
00607         }
00608     }
00609 
00610 
00612     //     GENERATE                                                       //
00614 
00618     template <class Generator_, typename T = typename Generator_::value_type>
00619     class generator2stream
00620     {
00621     public:
00623         typedef T value_type;
00624 
00625     private:
00626         Generator_ gen_;
00627         value_type current_;
00628 
00629     public:
00630         generator2stream(Generator_ g) :
00631             gen_(g), current_(gen_()) { }
00632 
00633         generator2stream(const generator2stream & a) : gen_(a.gen_), current_(a.current_) { }
00634 
00636         const value_type & operator * () const
00637         {
00638             return current_;
00639         }
00640 
00641         const value_type * operator -> () const
00642         {
00643             return &current_;
00644         }
00645 
00647         generator2stream & operator ++ ()
00648         {
00649             current_ = gen_();
00650             return *this;
00651         }
00652 
00654         bool empty() const
00655         {
00656             return false;
00657         }
00658     };
00659 
00663     template <class Generator_>
00664     generator2stream<Generator_> streamify(Generator_ gen_)
00665     {
00666         return generator2stream<Generator_>(gen_);
00667     }
00668 
00669 
00671     //     TRANSFORM                                                      //
00673 
00674     struct Stopper { };
00675 
00686     template <class Operation_,
00687               class Input1_,
00688               class Input2_ = Stopper,
00689               class Input3_ = Stopper,
00690               class Input4_ = Stopper,
00691               class Input5_ = Stopper,
00692               class Input6_ = Stopper
00693               >
00694     class transform
00695     {
00696         Operation_ & op;
00697         Input1_ & i1;
00698         Input2_ & i2;
00699         Input3_ & i3;
00700         Input4_ & i4;
00701         Input5_ & i5;
00702         Input6_ & i6;
00703 
00704     public:
00706         typedef typename Operation_::value_type value_type;
00707 
00708     private:
00709         value_type current;
00710 
00711     public:
00713         transform(Operation_ & o, Input1_ & i1_, Input2_ & i2_, Input3_ & i3_, Input4_ & i4_,
00714                   Input5_ & i5_, Input5_ & i6_) :
00715             op(o), i1(i1_), i2(i2_), i3(i3_), i4(i4_), i5(i5_), i6(i6_)
00716         {
00717             if (!empty())
00718                 current = op(*i1, *i2, *i3, *i4, *i5, *i6);
00719         }
00720 
00722         const value_type & operator * () const
00723         {
00724             return current;
00725         }
00726 
00727         const value_type * operator -> () const
00728         {
00729             return &current;
00730         }
00731 
00733         transform & operator ++ ()
00734         {
00735             ++i1;
00736             ++i2;
00737             ++i3;
00738             ++i4;
00739             ++i5;
00740             ++i6;
00741             if (!empty())
00742                 current = op(*i1, *i2, *i3, *i4, *i5, *i6);
00743 
00744             return *this;
00745         }
00746 
00748         bool empty() const
00749         {
00750             return i1.empty() || i2.empty() || i3.empty() ||
00751                    i4.empty() || i5.empty() || i6.empty();
00752         }
00753     };
00754 
00755     // Specializations
00756 
00758     //     TRANSFORM (1 input stream)                                     //
00760 
00767     template <class Operation_,
00768               class Input1_
00769               >
00770     class transform<Operation_, Input1_, Stopper, Stopper, Stopper, Stopper, Stopper>
00771     {
00772         Operation_ & op;
00773         Input1_ & i1;
00774 
00775     public:
00777         typedef typename Operation_::value_type value_type;
00778 
00779     private:
00780         value_type current;
00781 
00782     public:
00784         transform(Operation_ & o, Input1_ & i1_) : op(o), i1(i1_)
00785         {
00786             if (!empty())
00787                 current = op(*i1);
00788         }
00789 
00791         const value_type & operator * () const
00792         {
00793             return current;
00794         }
00795 
00796         const value_type * operator -> () const
00797         {
00798             return &current;
00799         }
00800 
00802         transform & operator ++ ()
00803         {
00804             ++i1;
00805             if (!empty())
00806                 current = op(*i1);
00807 
00808             return *this;
00809         }
00810 
00812         bool empty() const
00813         {
00814             return i1.empty();
00815         }
00816     };
00817 
00818 
00820     //     TRANSFORM (2 input streams)                                    //
00822 
00830     template <class Operation_,
00831               class Input1_,
00832               class Input2_
00833               >
00834     class transform<Operation_, Input1_, Input2_, Stopper, Stopper, Stopper, Stopper>
00835     {
00836         Operation_ & op;
00837         Input1_ & i1;
00838         Input2_ & i2;
00839 
00840     public:
00842         typedef typename Operation_::value_type value_type;
00843 
00844     private:
00845         value_type current;
00846 
00847     public:
00849         transform(Operation_ & o, Input1_ & i1_, Input2_ & i2_) : op(o), i1(i1_), i2(i2_)
00850         {
00851             if (!empty())
00852                 current = op(*i1, *i2);
00853         }
00854 
00856         const value_type & operator * () const
00857         {
00858             return current;
00859         }
00860 
00861         const value_type * operator -> () const
00862         {
00863             return &current;
00864         }
00865 
00867         transform & operator ++ ()
00868         {
00869             ++i1;
00870             ++i2;
00871             if (!empty())
00872                 current = op(*i1, *i2);
00873 
00874             return *this;
00875         }
00876 
00878         bool empty() const
00879         {
00880             return i1.empty() || i2.empty();
00881         }
00882     };
00883 
00884 
00886     //     TRANSFORM (3 input streams)                                    //
00888 
00897     template <class Operation_,
00898               class Input1_,
00899               class Input2_,
00900               class Input3_
00901               >
00902     class transform<Operation_, Input1_, Input2_, Input3_, Stopper, Stopper, Stopper>
00903     {
00904         Operation_ & op;
00905         Input1_ & i1;
00906         Input2_ & i2;
00907         Input3_ & i3;
00908 
00909     public:
00911         typedef typename Operation_::value_type value_type;
00912 
00913     private:
00914         value_type current;
00915 
00916     public:
00918         transform(Operation_ & o, Input1_ & i1_, Input2_ & i2_, Input3_ & i3_) :
00919             op(o), i1(i1_), i2(i2_), i3(i3_)
00920         {
00921             if (!empty())
00922                 current = op(*i1, *i2, *i3);
00923         }
00924 
00926         const value_type & operator * () const
00927         {
00928             return current;
00929         }
00930 
00931         const value_type * operator -> () const
00932         {
00933             return &current;
00934         }
00935 
00937         transform & operator ++ ()
00938         {
00939             ++i1;
00940             ++i2;
00941             ++i3;
00942             if (!empty())
00943                 current = op(*i1, *i2, *i3);
00944 
00945             return *this;
00946         }
00947 
00949         bool empty() const
00950         {
00951             return i1.empty() || i2.empty() || i3.empty();
00952         }
00953     };
00954 
00955 
00957     //     TRANSFORM (4 input streams)                                    //
00959 
00969     template <class Operation_,
00970               class Input1_,
00971               class Input2_,
00972               class Input3_,
00973               class Input4_
00974               >
00975     class transform<Operation_, Input1_, Input2_, Input3_, Input4_, Stopper, Stopper>
00976     {
00977         Operation_ & op;
00978         Input1_ & i1;
00979         Input2_ & i2;
00980         Input3_ & i3;
00981         Input4_ & i4;
00982 
00983     public:
00985         typedef typename Operation_::value_type value_type;
00986 
00987     private:
00988         value_type current;
00989 
00990     public:
00992         transform(Operation_ & o, Input1_ & i1_, Input2_ & i2_, Input3_ & i3_, Input4_ & i4_) :
00993             op(o), i1(i1_), i2(i2_), i3(i3_), i4(i4_)
00994         {
00995             if (!empty())
00996                 current = op(*i1, *i2, *i3, *i4);
00997         }
00998 
01000         const value_type & operator * () const
01001         {
01002             return current;
01003         }
01004 
01005         const value_type * operator -> () const
01006         {
01007             return &current;
01008         }
01009 
01011         transform & operator ++ ()
01012         {
01013             ++i1;
01014             ++i2;
01015             ++i3;
01016             ++i4;
01017             if (!empty())
01018                 current = op(*i1, *i2, *i3, *i4);
01019 
01020             return *this;
01021         }
01022 
01024         bool empty() const
01025         {
01026             return i1.empty() || i2.empty() || i3.empty() || i4.empty();
01027         }
01028     };
01029 
01030 
01032     //     TRANSFORM (5 input streams)                                    //
01034 
01045     template <class Operation_,
01046               class Input1_,
01047               class Input2_,
01048               class Input3_,
01049               class Input4_,
01050               class Input5_
01051               >
01052     class transform<Operation_, Input1_, Input2_, Input3_, Input4_, Input5_, Stopper>
01053     {
01054         Operation_ & op;
01055         Input1_ & i1;
01056         Input2_ & i2;
01057         Input3_ & i3;
01058         Input4_ & i4;
01059         Input5_ & i5;
01060 
01061     public:
01063         typedef typename Operation_::value_type value_type;
01064 
01065     private:
01066         value_type current;
01067 
01068     public:
01070         transform(Operation_ & o, Input1_ & i1_, Input2_ & i2_, Input3_ & i3_, Input4_ & i4_,
01071                   Input5_ & i5_) :
01072             op(o), i1(i1_), i2(i2_), i3(i3_), i4(i4_), i5(i5_)
01073         {
01074             if (!empty())
01075                 current = op(*i1, *i2, *i3, *i4, *i5);
01076         }
01077 
01079         const value_type & operator * () const
01080         {
01081             return current;
01082         }
01083 
01084         const value_type * operator -> () const
01085         {
01086             return &current;
01087         }
01088 
01090         transform & operator ++ ()
01091         {
01092             ++i1;
01093             ++i2;
01094             ++i3;
01095             ++i4;
01096             ++i5;
01097             if (!empty())
01098                 current = op(*i1, *i2, *i3, *i4, *i5);
01099 
01100             return *this;
01101         }
01102 
01104         bool empty() const
01105         {
01106             return i1.empty() || i2.empty() || i3.empty() || i4.empty() || i5.empty();
01107         }
01108     };
01109 
01110 
01112     //     MAKE TUPLE                                                     //
01114 
01123     template <class Input1_,
01124               class Input2_,
01125               class Input3_ = Stopper,
01126               class Input4_ = Stopper,
01127               class Input5_ = Stopper,
01128               class Input6_ = Stopper
01129               >
01130     class make_tuple
01131     {
01132         Input1_ & i1;
01133         Input2_ & i2;
01134         Input3_ & i3;
01135         Input4_ & i4;
01136         Input5_ & i5;
01137         Input6_ & i6;
01138 
01139     public:
01141         typedef typename stxxl::tuple<
01142             typename Input1_::value_type,
01143             typename Input2_::value_type,
01144             typename Input3_::value_type,
01145             typename Input4_::value_type,
01146             typename Input5_::value_type,
01147             typename Input6_::value_type
01148             > value_type;
01149 
01150     private:
01151         value_type current;
01152 
01153     public:
01155         make_tuple(
01156             Input1_ & i1_,
01157             Input2_ & i2_,
01158             Input3_ & i3_,
01159             Input4_ & i4_,
01160             Input5_ & i5_,
01161             Input6_ & i6_
01162             ) :
01163             i1(i1_), i2(i2_), i3(i3_), i4(i4_), i5(i5_), i6(i6_),
01164             current(value_type(*i1, *i2, *i3, *i4, *i5, *i6)) { }
01165 
01167         const value_type & operator * () const
01168         {
01169             return current;
01170         }
01171 
01172         const value_type * operator -> () const
01173         {
01174             return &current;
01175         }
01176 
01178         make_tuple & operator ++ ()
01179         {
01180             ++i1;
01181             ++i2;
01182             ++i3;
01183             ++i4;
01184             ++i5;
01185             ++i6;
01186 
01187             if (!empty())
01188                 current = value_type(*i1, *i2, *i3, *i4, *i5, *i6);
01189 
01190             return *this;
01191         }
01192 
01194         bool empty() const
01195         {
01196             return i1.empty() || i2.empty() || i3.empty() ||
01197                    i4.empty() || i5.empty() || i6.empty();
01198         }
01199     };
01200 
01201 
01207     template <class Input1_,
01208               class Input2_
01209               >
01210     class make_tuple<Input1_, Input2_, Stopper, Stopper, Stopper, Stopper>
01211     {
01212         Input1_ & i1;
01213         Input2_ & i2;
01214 
01215     public:
01217         typedef typename stxxl::tuple<
01218             typename Input1_::value_type,
01219             typename Input2_::value_type
01220             > value_type;
01221 
01222     private:
01223         value_type current;
01224 
01225     public:
01227         make_tuple(
01228             Input1_ & i1_,
01229             Input2_ & i2_
01230             ) :
01231             i1(i1_), i2(i2_)
01232         {
01233             if (!empty())
01234             {
01235                 current = value_type(*i1, *i2);
01236             }
01237         }
01238 
01240         const value_type & operator * () const
01241         {
01242             return current;
01243         }
01244 
01245         const value_type * operator -> () const
01246         {
01247             return &current;
01248         }
01249 
01251         make_tuple & operator ++ ()
01252         {
01253             ++i1;
01254             ++i2;
01255 
01256             if (!empty())
01257                 current = value_type(*i1, *i2);
01258 
01259             return *this;
01260         }
01261 
01263         bool empty() const
01264         {
01265             return i1.empty() || i2.empty();
01266         }
01267     };
01268 
01275     template <class Input1_,
01276               class Input2_,
01277               class Input3_
01278               >
01279     class make_tuple<Input1_, Input2_, Input3_, Stopper, Stopper, Stopper>
01280     {
01281         Input1_ & i1;
01282         Input2_ & i2;
01283         Input3_ & i3;
01284 
01285     public:
01287         typedef typename stxxl::tuple<
01288             typename Input1_::value_type,
01289             typename Input2_::value_type,
01290             typename Input3_::value_type
01291             > value_type;
01292 
01293     private:
01294         value_type current;
01295 
01296     public:
01298         make_tuple(
01299             Input1_ & i1_,
01300             Input2_ & i2_,
01301             Input3_ & i3_
01302             ) :
01303             i1(i1_), i2(i2_), i3(i3_),
01304             current(value_type(*i1, *i2, *i3)) { }
01305 
01307         const value_type & operator * () const
01308         {
01309             return current;
01310         }
01311 
01312         const value_type * operator -> () const
01313         {
01314             return &current;
01315         }
01316 
01318         make_tuple & operator ++ ()
01319         {
01320             ++i1;
01321             ++i2;
01322             ++i3;
01323 
01324             if (!empty())
01325                 current = value_type(*i1, *i2, *i3);
01326 
01327             return *this;
01328         }
01329 
01331         bool empty() const
01332         {
01333             return i1.empty() || i2.empty() || i3.empty();
01334         }
01335     };
01336 
01344     template <class Input1_,
01345               class Input2_,
01346               class Input3_,
01347               class Input4_
01348               >
01349     class make_tuple<Input1_, Input2_, Input3_, Input4_, Stopper, Stopper>
01350     {
01351         Input1_ & i1;
01352         Input2_ & i2;
01353         Input3_ & i3;
01354         Input4_ & i4;
01355 
01356     public:
01358         typedef typename stxxl::tuple<
01359             typename Input1_::value_type,
01360             typename Input2_::value_type,
01361             typename Input3_::value_type,
01362             typename Input4_::value_type
01363             > value_type;
01364 
01365     private:
01366         value_type current;
01367 
01368     public:
01370         make_tuple(
01371             Input1_ & i1_,
01372             Input2_ & i2_,
01373             Input3_ & i3_,
01374             Input4_ & i4_
01375             ) :
01376             i1(i1_), i2(i2_), i3(i3_), i4(i4_),
01377             current(value_type(*i1, *i2, *i3, *i4)) { }
01378 
01380         const value_type & operator * () const
01381         {
01382             return current;
01383         }
01384 
01385         const value_type * operator -> () const
01386         {
01387             return &current;
01388         }
01389 
01391         make_tuple & operator ++ ()
01392         {
01393             ++i1;
01394             ++i2;
01395             ++i3;
01396             ++i4;
01397 
01398             if (!empty())
01399                 current = value_type(*i1, *i2, *i3, *i4);
01400 
01401             return *this;
01402         }
01403 
01405         bool empty() const
01406         {
01407             return i1.empty() || i2.empty() || i3.empty() ||
01408                    i4.empty();
01409         }
01410     };
01411 
01420     template <
01421         class Input1_,
01422         class Input2_,
01423         class Input3_,
01424         class Input4_,
01425         class Input5_
01426         >
01427     class make_tuple<Input1_, Input2_, Input3_, Input4_, Input5_, Stopper>
01428     {
01429         Input1_ & i1;
01430         Input2_ & i2;
01431         Input3_ & i3;
01432         Input4_ & i4;
01433         Input5_ & i5;
01434 
01435     public:
01437         typedef typename stxxl::tuple<
01438             typename Input1_::value_type,
01439             typename Input2_::value_type,
01440             typename Input3_::value_type,
01441             typename Input4_::value_type,
01442             typename Input5_::value_type
01443             > value_type;
01444 
01445     private:
01446         value_type current;
01447 
01448     public:
01450         make_tuple(
01451             Input1_ & i1_,
01452             Input2_ & i2_,
01453             Input3_ & i3_,
01454             Input4_ & i4_,
01455             Input5_ & i5_
01456             ) :
01457             i1(i1_), i2(i2_), i3(i3_), i4(i4_), i5(i5_),
01458             current(value_type(*i1, *i2, *i3, *i4, *i5)) { }
01459 
01461         const value_type & operator * () const
01462         {
01463             return current;
01464         }
01465 
01466         const value_type * operator -> () const
01467         {
01468             return &current;
01469         }
01470 
01472         make_tuple & operator ++ ()
01473         {
01474             ++i1;
01475             ++i2;
01476             ++i3;
01477             ++i4;
01478             ++i5;
01479 
01480             if (!empty())
01481                 current = value_type(*i1, *i2, *i3, *i4, *i5);
01482 
01483             return *this;
01484         }
01485 
01487         bool empty() const
01488         {
01489             return i1.empty() || i2.empty() || i3.empty() ||
01490                    i4.empty() || i5.empty();
01491         }
01492     };
01493 
01494 
01496 }
01497 
01498 __STXXL_END_NAMESPACE
01499 
01500 
01501 #include <stxxl/bits/stream/choose.h>
01502 #include <stxxl/bits/stream/unique.h>
01503 
01504 
01505 #endif // !STXXL_STREAM_HEADER
01506 // vim: et:ts=4:sw=4

Generated by  doxygen 1.7.1