/* -*- 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 // for placement new #include #include #include #include #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 struct __uninitialized_copy { template 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(&*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 { template 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::max(); typedef typename iterator_traits<_ForwardIterator>:: value_type value_type; const size_t kSize = sizeof(value_type); if (len > 0 && static_cast(kMaxSize) / kSize > static_cast(len)) { std::memmove(static_cast(&*dest), static_cast(&*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 { template static _ForwardIterator uninitialized_copy(_InputIterator begin, _InputIterator end, _ForwardIterator dest) { for (; begin != end; ++begin, ++dest) { *dest = *begin; } return dest; } }; template 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::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 struct __uninitialized_fill { template static void uninitialized_fill(_ForwardIterator *begin, _ForwardIterator *end, const _T& val) { for (; begin < end; ++begin) new (static_cast(&*begin)) _ForwardIterator(val); } }; template<> struct __uninitialized_fill { template 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 inline void uninitialized_fill(_ForwardIterator *begin, _ForwardIterator *end, const _T& val) { const bool pod = is_pod<_ForwardIterator>::value; return __uninitialized_fill::uninitialized_fill(begin, end, val); } } // namespace std #endif // ANDROID_ASTL_MEMORY__