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 41namespace 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 52template<typename _T> inline const _T& min(const _T& left, const _T& right) 53{ 54 if (left < right) return left; 55 return right; 56} 57 58template<typename _T> inline const _T& max(const _T& left, const _T& right) 59{ 60 if (right < left) return left; 61 return right; 62} 63 64template<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. 75template<typename _Category> 76struct 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-). 89template<> 90struct 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) 116template<typename _InputIterator, typename _OutputIterator> 117inline _OutputIterator 118copy(_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 135template<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 145template<> 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 157template<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. 164inline 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 174inline 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 183inline 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 192template<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 205template<> 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 220template<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. 228inline 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 236inline 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 244inline 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. 261template<typename _InputIterator1, typename _InputIterator2> 262inline 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. 281template<typename _InputIterator1, typename _InputIterator2, typename _BinaryPredicated> 282inline 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