| /* -*- 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> |
| |
| #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, uninitialized_copy |
| // degrades to a memmove call. |
| |
| template<bool> struct __uninitialized_copy |
| { |
| template<typename _InputIterator, typename _ForwardIterator> |
| static _ForwardIterator *uninitialized_copy(const _InputIterator *begin, |
| const _InputIterator *end, |
| _ForwardIterator *dest) |
| { |
| _ForwardIterator *result = dest; |
| for (; begin < end; ++begin, ++dest) |
| new (static_cast<void*>(dest)) _ForwardIterator(*begin); |
| return result; |
| } |
| }; |
| |
| template<> struct __uninitialized_copy<true> |
| { |
| template<typename _InputIterator, typename _ForwardIterator> |
| static _ForwardIterator *uninitialized_copy(const _InputIterator *begin, |
| const _InputIterator *end, |
| _ForwardIterator *dest) |
| { |
| const ptrdiff_t len = end - begin; |
| const size_t kMaxSizeT = ~((size_t)0); |
| const size_t kSize = sizeof(_InputIterator); |
| |
| if (len > 0 && kMaxSizeT / kSize > static_cast<size_t>(len)) |
| { |
| std::memmove(static_cast<void*>(dest), |
| static_cast<const void*>(begin), kSize * len); |
| } |
| return dest; |
| } |
| }; |
| |
| // The real STL takes iterators, we take pointers for now. |
| template<typename _InputIterator, typename _ForwardIterator> |
| inline _ForwardIterator* uninitialized_copy(const _InputIterator *begin, |
| const _InputIterator *end, |
| _ForwardIterator *dest) |
| { |
| const bool both_pod = |
| is_pod<_InputIterator>::value && is_pod<_ForwardIterator>::value; |
| return __uninitialized_copy<both_pod>::uninitialized_copy(begin, end, dest); |
| } |
| |
| // 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__ |