1 /* -*- c++ -*- */ 2 /* 3 * Copyright (C) 2009 The Android Open Source Project 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * * Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * * Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in 13 * the documentation and/or other materials provided with the 14 * distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 19 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 20 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 22 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 23 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 24 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 25 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 26 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 * SUCH DAMAGE. 28 */ 29 30 #ifndef ANDROID_ASTL_ALGORITHM__ 31 #define ANDROID_ASTL_ALGORITHM__ 32 33 #include <cstddef> 34 #include <cstring> 35 #include <iterator> 36 #include <type_traits.h> 37 #ifndef ANDROID_ASTL_TYPE_TRAITS_H__ 38 #error "Wrong file included!" 39 #endif 40 41 namespace std { 42 43 // This file contains the following template functions: 44 // - min 45 // - max 46 // - swap 47 // - fill 48 // - fill_n 49 // - copy 50 // - equal 51 52 template<typename _T> inline const _T& min(const _T& left, const _T& right) 53 { 54 if (left < right) return left; 55 return right; 56 } 57 58 template<typename _T> inline const _T& max(const _T& left, const _T& right) 59 { 60 if (right < left) return left; 61 return right; 62 } 63 64 template<typename _T> inline void swap(_T& left, _T& right) 65 { 66 _T tmp = left; 67 left = right; 68 right = tmp; 69 } 70 71 72 // Basic iterators, loop over the elements, we don't know how many 73 // elements we need to copy. See the random access specialization 74 // below. 75 template<typename _Category> 76 struct copy_move { 77 template<typename _InputIterator, typename _OutputIterator> 78 static _OutputIterator 79 __copy_move(_InputIterator first, _InputIterator last, _OutputIterator res) { 80 for (; first != last; ++res, ++first) { 81 *res = *first; 82 } 83 return res; 84 } 85 }; 86 87 // For random access iterators, we know how many elements we have to 88 // copy (random iterators support operator-). 89 template<> 90 struct copy_move<random_access_iterator_tag> { 91 template<typename _InputIterator, typename _OutputIterator> 92 static _OutputIterator 93 __copy_move(_InputIterator first, _InputIterator last, _OutputIterator res) { 94 typedef typename iterator_traits<_InputIterator>::difference_type 95 difference_type; 96 97 for (difference_type n = last - first; n > 0; --n) { 98 *res = *first; 99 ++first; 100 ++res; 101 } 102 return res; 103 } 104 }; 105 106 // TODO: for simple case and wrapper iterator, should degrade to memmove. 107 108 // copy elements in the range [first, last) into the range [result, 109 // result + (last - first)) starting from first and proceeding to 110 // last. 111 // 112 // For each non negative n < (last - first) performs: 113 // *(result + n) = *(first + n) 114 // @require result should not be in the [first, last) range. 115 // @return result + (last - first) 116 template<typename _InputIterator, typename _OutputIterator> 117 inline _OutputIterator 118 copy(_InputIterator first, _InputIterator last, _OutputIterator res) { 119 typedef typename iterator_traits<_InputIterator>::iterator_category 120 _Category; 121 122 return copy_move<_Category>::__copy_move( 123 android::iter<_InputIterator>::base(first), 124 android::iter<_InputIterator>::base(last), 125 res); 126 } 127 128 // fill the range [begin, end) with copies of value, return nothing. 129 // fill_n the range [begin, begin + n) with copies of value, return 130 // the pointer at begin + n. 131 // 132 // TODO: fill and fill_n should take forward and output iterators for 133 // begin and end params. Fix this when iterator are defined. 134 135 template<bool> struct __fill 136 { 137 template<typename _T> static void fill(_T *begin, const _T *end, 138 const _T& value) 139 { 140 for (; begin < end; ++begin) 141 *begin = value; 142 } 143 }; 144 145 template<> struct __fill<true> // scalar version 146 { 147 template<typename _T> static void fill(_T *begin, const _T *end, 148 const _T& value) 149 { 150 const _T tmp = value; 151 152 for (; begin < end; ++begin) 153 *begin = tmp; 154 } 155 }; 156 157 template<typename _T> void fill(_T *begin, _T *end, const _T& value) 158 { 159 const bool is_scalar = std::is_scalar<_T>::value; 160 __fill<is_scalar>::fill(begin, end, value); 161 } 162 163 // Specialization: for one-byte types use memset. 164 inline void fill(unsigned char *begin, unsigned char *end, 165 const unsigned char& value) 166 { 167 if (begin < end) 168 { 169 const int tmp = value; 170 std::memset(begin, tmp, end - begin); 171 } 172 } 173 174 inline void fill(signed char *begin, signed char *end, const signed char& value) 175 { 176 if (begin < end) 177 { 178 const int tmp = value; 179 std::memset(begin, tmp, end - begin); 180 } 181 } 182 183 inline void fill(char *begin, char *end, const char& value) 184 { 185 if (begin < end) 186 { 187 const int tmp = value; 188 std::memset(begin, tmp, end - begin); 189 } 190 } 191 192 template<bool> struct __fill_n 193 { 194 template<typename _T> static _T *fill_n(_T *begin, size_t num, 195 const _T& value) 196 { 197 for (size_t i = 0; i < num; ++i, ++begin) 198 { 199 *begin = value; 200 } 201 return begin; 202 } 203 }; 204 205 template<> struct __fill_n<true> // scalar version 206 { 207 template<typename _T> static _T *fill_n(_T *begin, size_t num, 208 const _T& value) 209 { 210 const _T tmp = value; 211 212 for (size_t i = 0; i < num; ++i, ++begin) 213 { 214 *begin = tmp; 215 } 216 return begin; 217 } 218 }; 219 220 template<typename _T> _T *fill_n(_T *begin, size_t n, const _T& value) 221 { 222 const bool is_scalar = std::is_scalar<_T>::value; 223 return __fill_n<is_scalar>::fill_n(begin, n, value); 224 } 225 226 227 // Specialization: for one-byte types uses memset. 228 inline unsigned char *fill_n(unsigned char *begin, size_t num, 229 const unsigned char& value) 230 { 231 const int tmp = value; 232 std::memset(begin, tmp, num); 233 return begin + num; 234 } 235 236 inline signed char *fill_n(signed char *begin, size_t num, 237 const signed char& value) 238 { 239 const int tmp = value; 240 std::memset(begin, tmp, num); 241 return begin + num; 242 } 243 244 inline char *fill_n(char *begin, size_t num, const char& value) 245 { 246 const int tmp = value; 247 std::memset(begin, tmp, num); 248 return begin + num; 249 } 250 251 252 // Test a range for element-wise equality using operator== 253 // @param begin1 An input iterator. 254 // @param end1 An input iterator. 255 // @param begin2 An input iterator. 256 // @return true if all the elements of the range are equal. 257 // TODO: When we have a proper structure for iterator as opposed to 258 // just pointers, we should be able to the get the type for the values 259 // referenced by the iterator and default to memcmp for simple types. 260 // TODO: equal should degrade to memcmp for pod. 261 template<typename _InputIterator1, typename _InputIterator2> 262 inline bool equal(_InputIterator1 begin1, _InputIterator1 end1, 263 _InputIterator2 begin2) 264 { 265 for (; begin1 < end1; ++begin1, ++begin2) 266 { 267 if (!(*begin1 == *begin2)) 268 { 269 return false; 270 } 271 } 272 return true; 273 } 274 275 // Test a range for element-wise equality using operator== 276 // @param begin1 An input iterator. 277 // @param end1 An input iterator. 278 // @param begin2 An input iterator. 279 // @param binary_pred A binary predicate function. 280 // @return true if all the elements of the range are equal. 281 template<typename _InputIterator1, typename _InputIterator2, typename _BinaryPredicated> 282 inline bool equal(_InputIterator1 begin1, _InputIterator1 end1, 283 _InputIterator2 begin2, _BinaryPredicated binary_predicate) 284 { 285 for (; begin1 < end1; ++begin1, ++begin2) 286 { 287 if (!bool(binary_predicate(*begin1, *begin2))) 288 { 289 return false; 290 } 291 } 292 return true; 293 } 294 295 } // namespace std 296 297 #endif 298