| /* -*- c++ -*- */ |
| /* |
| * Copyright (C) 2009 The Android Open Source Project |
| * All rights reserved. |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions |
| * are met: |
| * * Redistributions of source code must retain the above copyright |
| * notice, this list of conditions and the following disclaimer. |
| * * Redistributions in binary form must reproduce the above copyright |
| * notice, this list of conditions and the following disclaimer in |
| * the documentation and/or other materials provided with the |
| * distribution. |
| * |
| * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
| * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
| * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS |
| * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE |
| * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, |
| * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, |
| * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS |
| * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED |
| * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, |
| * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT |
| * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
| * SUCH DAMAGE. |
| */ |
| |
| #ifndef ANDROID_ASTL_MEMORY__ |
| #define ANDROID_ASTL_MEMORY__ |
| |
| #include "type_traits.h" |
| #include <new> // for placement new |
| #include <cstring> |
| #include <algorithm> |
| #include <iterator> |
| #include <limits> |
| |
| #if defined(_InputIterator) || defined(_ForwardIterator) |
| #error "_InputIterator or _ForwardIterator are already defined." |
| #endif |
| |
| namespace std { |
| |
| // uninitialized_copy is used when memory allocation and object |
| // construction need to happen in separate steps. For each instance in |
| // the input range a copy is created and placed in the corresponding |
| // memory pointed by dest. |
| // If the input range is made of pod instances AND both input and |
| // destination iterators are random access ones, uninitialized_copy |
| // degrades to a memmove call. |
| // Returns an iterator pass the end of the destination range. |
| |
| // Default implementation used when iterators are not random access |
| // and the value type are not both POD. |
| template<bool, typename _InputIteratorTag, typename _ForwardIteratorTag> |
| struct __uninitialized_copy |
| { |
| template<typename _InputIterator, typename _ForwardIterator> |
| static _ForwardIterator uninitialized_copy(_InputIterator begin, |
| _InputIterator end, |
| _ForwardIterator dest) { |
| typedef typename iterator_traits<_ForwardIterator>:: |
| value_type value_type; |
| for (; begin != end; ++begin, ++dest) { |
| new (static_cast<void*>(&*dest)) value_type(*begin); |
| } |
| return dest; |
| } |
| }; |
| |
| // Full specialization when the src and dest types are pod && both |
| // iterators are random access. |
| template<> |
| struct __uninitialized_copy<true, |
| random_access_iterator_tag, |
| random_access_iterator_tag> |
| { |
| template<typename _InputIterator, typename _ForwardIterator> |
| static _ForwardIterator uninitialized_copy(_InputIterator begin, |
| _InputIterator end, |
| _ForwardIterator dest) |
| { |
| typedef typename iterator_traits<_InputIterator>:: |
| difference_type difference_type; |
| const difference_type len = std::distance(begin, end); |
| const difference_type kMaxSize = |
| std::numeric_limits<difference_type>::max(); |
| |
| typedef typename iterator_traits<_ForwardIterator>:: |
| value_type value_type; |
| const size_t kSize = sizeof(value_type); |
| |
| if (len > 0 && |
| static_cast<size_t>(kMaxSize) / kSize > static_cast<size_t>(len)) { |
| std::memmove(static_cast<void*>(&*dest), |
| static_cast<const void*>(&*begin), kSize * len); |
| return dest + len; |
| } else { |
| return dest; |
| } |
| } |
| }; |
| |
| // TODO: If placement new degrades to assignement for POD, we can get |
| // rid of this one. |
| // Bothe pod but not both random access |
| template<> struct __uninitialized_copy<true, |
| input_iterator_tag, |
| forward_iterator_tag> |
| { |
| template<typename _InputIterator, typename _ForwardIterator> |
| static _ForwardIterator uninitialized_copy(_InputIterator begin, |
| _InputIterator end, |
| _ForwardIterator dest) { |
| for (; begin != end; ++begin, ++dest) { |
| *dest = *begin; |
| } |
| return dest; |
| } |
| }; |
| |
| |
| template<typename _InputIterator, typename _ForwardIterator> |
| inline _ForwardIterator uninitialized_copy(_InputIterator begin, |
| _InputIterator end, |
| _ForwardIterator dest) |
| { |
| typedef typename iterator_traits<_InputIterator>::value_type _ValueType1; |
| typedef typename iterator_traits<_ForwardIterator>::value_type _ValueType2; |
| |
| const bool both_pod = |
| is_pod<_ValueType1>::value && is_pod<_ValueType2>::value; |
| |
| return __uninitialized_copy<both_pod, |
| typename iterator_traits<_InputIterator>::iterator_category, |
| typename iterator_traits<_ForwardIterator>::iterator_category>:: |
| uninitialized_copy(begin, end, dest); |
| } |
| |
| // TODO: replace pointers with iterator below. |
| |
| // uninitialized_fill is used when memory allocation and object |
| // construction need to happen in separate steps. uninitialized_fill |
| // creates a copy of 'obj' in the location pointed by the interator, |
| // using the object's class copy constructor. |
| |
| template<bool> struct __uninitialized_fill |
| { |
| template<typename _ForwardIterator, typename _T> |
| static void uninitialized_fill(_ForwardIterator *begin, |
| _ForwardIterator *end, |
| const _T& val) |
| { |
| for (; begin < end; ++begin) |
| new (static_cast<void*>(&*begin)) _ForwardIterator(val); |
| } |
| }; |
| |
| template<> struct __uninitialized_fill<true> |
| { |
| template<typename _ForwardIterator, typename _T> |
| static void uninitialized_fill(_ForwardIterator *begin, |
| _ForwardIterator *end, |
| const _T& val) |
| { |
| std::fill(begin, end, val); |
| } |
| }; |
| |
| // The real STL takes iterators, we take pointers for now. |
| template<typename _ForwardIterator, typename _T> |
| inline void uninitialized_fill(_ForwardIterator *begin, |
| _ForwardIterator *end, |
| const _T& val) |
| { |
| const bool pod = is_pod<_ForwardIterator>::value; |
| return __uninitialized_fill<pod>::uninitialized_fill(begin, end, val); |
| } |
| |
| } // namespace std |
| |
| #endif // ANDROID_ASTL_MEMORY__ |