Simple Application Framework
1
|
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