Simple Application Framework  1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines
Saf/Algo/Range.h
Go to the documentation of this file.
00001 /*
00002     This file is part of Simple Application Framework (Saf) library.
00003     Copyright (C) 2010 - 2012 Ondrej Danek <ondrej.danek@gmail.com>
00004 
00005     This library is free software: you can redistribute it and/or modify
00006     it under the terms of the GNU General Public License as published 
00007     by the Free Software Foundation, either version 3 of the License, or
00008     (at your option) any later version.
00009 
00010     Saf is distributed in the hope that it will be useful,
00011     but WITHOUT ANY WARRANTY; without even the implied warranty of
00012     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013     GNU General Public License for more details.
00014 
00015     You should have received a copy of the GNU General Public License
00016     along with Simple Application Framework library. If not, 
00017     see <http://www.gnu.org/licenses/>.
00018 */
00019 
00028 #ifndef SAF_ALGO_RANGE_H
00029 #define SAF_ALGO_RANGE_H
00030 
00031 #include "../Type.h"
00032 #include "../Type/IteratorTraits.h"
00033 #include "../IndexOutOfRangeException.h"
00034 
00035 namespace Saf
00036 {
00038     namespace Internal
00039     {
00040         namespace AlgoRange
00041         {
00042             template <class RanIter>
00043             inline Saf::Size Distance(RanIter begin, RanIter end, Saf::Type::IteratorCategory::RandomAccessCategory)
00044             {
00045                 return end - begin;
00046             }
00047 
00048             template <class FwdIter>
00049             inline Saf::Size Distance(FwdIter begin, FwdIter end, Saf::Type::IteratorCategory::ForwardCategory)
00050             {
00051                 Saf::Size dist = 0;
00052 
00053                 while (begin != end)
00054                 {
00055                     ++begin;
00056                     ++dist;
00057                 }
00058 
00059                 return dist;
00060             }
00061 
00062             template <class RanIter>
00063             inline void Advance(RanIter &it, Saf::Size dist, Saf::Type::IteratorCategory::RandomAccessCategory)
00064             {
00065                 it += dist;
00066             }
00067 
00068             template <class InpIter>
00069             inline void Advance(InpIter &it, Saf::Size dist, Saf::Type::IteratorCategory::ForwardCategory)
00070             {
00071                 while (dist-- > 0)
00072                 {
00073                     ++it;
00074                 }
00075             }
00076 
00081             template <class RanIter>
00082             void Rotate(RanIter begin, RanIter middle, RanIter end, Saf::Type::IteratorCategory::RandomAccessCategory)
00083             {
00084                 if (middle < begin || end <= middle)
00085                 {
00086                     throw Saf::IndexOutOfRangeException(SAF_SOURCE_LOCATION);
00087                 }
00088 
00089                 Saf::Size step = middle - begin;        
00090 
00091                 if (step > 0)
00092                 {
00093                     Saf::Size len = end - begin;
00094                     Saf::Size done = 0; 
00095                     RanIter first = begin, cur, next;
00096                     typename Saf::Type::IteratorTraits<RanIter>::ValType tmpVal;
00097 
00098                     while (done < len)
00099                     {
00100                         cur = first;
00101                         next = first + step;
00102 
00103                         tmpVal = *first;
00104                         ++done;
00105                 
00106                         while (next != first) 
00107                         {
00108                             ++done;
00109 
00110                             *cur = *next;
00111                             cur = next;
00112                             next += step;
00113                     
00114                             if (next >= end)
00115                             {
00116                                 next -= len;
00117                             }
00118                         }
00119 
00120                         *cur = tmpVal;
00121                         ++first;
00122                     }
00123                 }
00124             }
00125 
00130             template <class FwdIter>
00131             inline void Rotate(FwdIter begin, FwdIter middle, FwdIter end, Saf::Type::IteratorCategory::ForwardCategory)
00132             {
00133                 FwdIter next = middle;
00134 
00135                 while (begin != next)
00136                 {
00137                     Saf::Algo::Swap(*begin, *next);
00138                     ++begin;
00139                     ++next;
00140 
00141                     if (next == end)
00142                     {
00143                         next = middle;
00144                     }
00145                     else if (begin == middle)
00146                     {
00147                         middle = next;
00148                     }
00149                 }        
00150             }
00151         }
00152     }
00155     namespace Algo
00156     {
00161         namespace Range
00162         {
00170             template <class Iter>
00171             inline Size Distance(Iter begin, Iter end)
00172             {
00173                 return Internal::AlgoRange::Distance(begin, end, Type::IteratorTraits<Iter>::Category());
00174             }
00175 
00183             template <class Iter>
00184             inline void Advance(Iter &it, Size dist)
00185             {
00186                 Internal::AlgoRange::Advance(it, dist, Type::IteratorTraits<Iter>::Category());
00187             }
00188 
00195             template <class FwdIter, class Func>
00196             inline Func ForEach(FwdIter begin, FwdIter end, Func func)
00197             {
00198                 while (begin != end)
00199                 {
00200                     func(*begin);
00201                     ++begin;
00202                 }
00203 
00204                 return func;
00205             }
00206 
00213             template <class FwdIter, class Val>
00214             inline void Fill(FwdIter begin, FwdIter end, const Val& val)
00215             {
00216                 while (begin != end)
00217                 {
00218                     *begin = val;
00219                     ++begin;
00220                 }
00221             }
00222 
00230             template <class FwdIter, class Val>
00231             inline void FillFirst(FwdIter first, Size num, const Val& val)
00232             {
00233                 while (num-- > 0)
00234                 {
00235                     *first = val;
00236                     ++first;
00237                 }
00238             }
00239 
00247             template <class FwdIter, class Val>
00248             inline bool AllEqualTo(FwdIter begin, FwdIter end, const Val& val)
00249             {
00250                 while (begin != end)
00251                 {
00252                     if (*begin != val)
00253                     {
00254                         return false;
00255                     }
00256 
00257                     ++begin;
00258                 }
00259 
00260                 return true;
00261             }
00262 
00270             template <class FwdIter, class Val>
00271             inline bool AnyEqualTo(FwdIter begin, FwdIter end, const Val& val)
00272             {
00273                 while (begin != end)
00274                 {
00275                     if (*begin == val)
00276                     {
00277                         return true;
00278                     }
00279 
00280                     ++begin;
00281                 }
00282 
00283                 return false;
00284             }
00285 
00297             template <class FwdIter1, class FwdIter2>
00298             inline bool Equal(FwdIter1 r1Begin, FwdIter1 r1End, FwdIter2 r2Begin)
00299             {
00300                 while (r1Begin != r1End)
00301                 {
00302                     if (*r1Begin != *r2Begin)
00303                     {
00304                         return false;
00305                     }
00306 
00307                     ++r1Begin;
00308                     ++r2Begin;
00309                 }
00310 
00311                 return true;
00312             }
00313 
00325             template <class FwdIter1, class FwdIter2>
00326             inline bool Identical(FwdIter1 r1Begin, FwdIter1 r1End, FwdIter2 r2Begin, FwdIter2 r2End)
00327             {
00328                 while (r1Begin != r1End && r2Begin != r2End)
00329                 {
00330                     if (*r1Begin != *r2Begin)
00331                     {
00332                         return false;
00333                     }
00334 
00335                     ++r1Begin;
00336                     ++r2Begin;
00337                 }
00338 
00339                 return (r1Begin == r1End && r2Begin == r2End);
00340             }
00341 
00353             template <class FwdIterIn, class FwdIterOut>
00354             inline FwdIterOut Copy(FwdIterIn begin, FwdIterIn end, FwdIterOut dest)
00355             {
00356                 while (begin != end)
00357                 {
00358                     *dest = *begin;
00359                     ++dest;
00360                     ++begin;
00361                 }
00362 
00363                 return dest;
00364             }
00365 
00372             template <class FwdIter, class Val>
00373             inline Size Count(FwdIter begin, FwdIter end, const Val& val)
00374             {
00375                 Size num = 0;
00376 
00377                 while (begin != end)
00378                 {
00379                     if (*begin == val)
00380                     {
00381                         ++num;
00382                     }
00383                     ++begin;
00384                 }
00385 
00386                 return num;
00387             }
00388 
00396             template <class FwdIter, class Pred>
00397             inline Size CountIf(FwdIter begin, FwdIter end, Pred pred)
00398             {
00399                 Size num = 0;
00400 
00401                 while (begin != end)
00402                 {
00403                     if (pred(*begin))
00404                     {
00405                         ++num;
00406                     }
00407                     ++begin;
00408                 }
00409 
00410                 return num;
00411             }
00412 
00419             template <class BidIter>
00420             inline void Reverse(BidIter begin, BidIter end)
00421             {
00422                 while (begin != end)
00423                 {
00424                     if (begin == --end)
00425                     {
00426                         break;
00427                     }
00428 
00429                     Swap(*begin, *end);
00430                     ++begin;
00431                 }
00432             }
00433 
00441             template <class Iter>
00442             inline void Rotate(Iter begin, Iter middle, Iter end)
00443             {
00444                 Internal::AlgoRange::Rotate(begin, middle, end, Type::IteratorTraits<Iter>::Category());
00445             }
00446         }
00447     }
00448 }
00449 
00450 #endif