fast_unique_copy.hh

00001 /* vim: set sw=4 sts=4 et foldmethod=syntax : */
00002 
00003 /*
00004  * Copyright (c) 2006, 2007, 2009 Ciaran McCreesh
00005  *
00006  * This file is part of the Paludis package manager. Paludis is free software;
00007  * you can redistribute it and/or modify it under the terms of the GNU General
00008  * Public License version 2, as published by the Free Software Foundation.
00009  *
00010  * Paludis is distributed in the hope that it will be useful, but WITHOUT ANY
00011  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
00012  * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
00013  * details.
00014  *
00015  * You should have received a copy of the GNU General Public License along with
00016  * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
00017  * Place, Suite 330, Boston, MA  02111-1307  USA
00018  */
00019 
00020 #ifndef PALUDIS_GUARD_PALUDIS_REPOSITORIES_VIRTUALS_FAST_UNIQUE_COPY_HH
00021 #define PALUDIS_GUARD_PALUDIS_REPOSITORIES_VIRTUALS_FAST_UNIQUE_COPY_HH 1
00022 
00023 #include <paludis/util/iterator_funcs.hh>
00024 #include <functional>
00025 
00026 namespace paludis
00027 {
00028     /**
00029      * For use by fast_unique_copy only.
00030      */
00031     namespace fast_unique_copy_internals
00032     {
00033         /**
00034          * For use by fast_unique_copy only.
00035          */
00036         template <typename I_, typename O_, typename C_>
00037         void
00038         real_fast_unique_copy(const I_ & start, const I_ & end, const I_ & full_end, O_ out,
00039                 C_ comp, const I_ & mbgt)
00040         {
00041             if (start != end)
00042             {
00043                 // if our final item is less than or equal to mbgt, there're no
00044                 // matches in this block
00045                 if ((mbgt != full_end) && ((comp(*previous(end), *mbgt)) || (! comp(*mbgt, *previous(end)))))
00046                     return;
00047 
00048                 // if our first item is equal to our last item, we have exactly
00049                 // one unique item in this sequence
00050                 if ((! comp(*start, *previous(end))) && (! comp(*previous(end), *start)))
00051                 {
00052                     *out = *start;
00053                     ++out;
00054                 }
00055                 else
00056                 {
00057                     I_ mid = start + (std::distance(start, end) >> 1);
00058                     real_fast_unique_copy(start, mid, full_end, out, comp, mbgt);
00059                     real_fast_unique_copy(mid, end, full_end, out, comp, previous(mid));
00060                 }
00061             }
00062         }
00063     }
00064 
00065     /**
00066      * Extract unique elements from a sorted range of random access iterators.
00067      */
00068     template <typename I_, typename O_>
00069     void
00070     fast_unique_copy(const I_ & start, const I_ & end, O_ out)
00071     {
00072         fast_unique_copy_internals::real_fast_unique_copy(start, end, end, out,
00073                 std::less<typename std::iterator_traits<I_>::value_type>(),
00074                 end);
00075     }
00076 
00077     /**
00078      * Extract unique elements from a sorted range of random access iterators.
00079      */
00080     template <typename I_, typename O_, typename C_>
00081     void
00082     fast_unique_copy(const I_ & start, const I_ & end, O_ out, C_ comp)
00083     {
00084         fast_unique_copy_internals::real_fast_unique_copy(start, end, end, out, comp, end);
00085     }
00086 }
00087 
00088 #endif

Generated on Mon Sep 21 10:36:08 2009 for paludis by  doxygen 1.5.4