Home | History | Annotate | Download | only in include
      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_MEMORY__
     31 #define ANDROID_ASTL_MEMORY__
     32 
     33 #include "type_traits.h"
     34 #include <new>  // for placement new
     35 #include <cstring>
     36 #include <algorithm>
     37 #include <iterator>
     38 #include <limits>
     39 
     40 #if defined(_InputIterator) || defined(_ForwardIterator)
     41 #error "_InputIterator or _ForwardIterator are already defined."
     42 #endif
     43 
     44 namespace std {
     45 
     46 // uninitialized_copy is used when memory allocation and object
     47 // construction need to happen in separate steps. For each instance in
     48 // the input range a copy is created and placed in the corresponding
     49 // memory pointed by dest.
     50 // If the input range is made of pod instances AND both input and
     51 // destination iterators are random access ones, uninitialized_copy
     52 // degrades to a memmove call.
     53 // Returns an iterator pass the end of the destination range.
     54 
     55 // Default implementation used when iterators are not random access
     56 // and the value type are not both POD.
     57 template<bool, typename _InputIteratorTag, typename _ForwardIteratorTag>
     58 struct __uninitialized_copy
     59 {
     60     template<typename _InputIterator, typename _ForwardIterator>
     61     static _ForwardIterator uninitialized_copy(_InputIterator begin,
     62                                                _InputIterator end,
     63                                                _ForwardIterator dest) {
     64         typedef typename iterator_traits<_ForwardIterator>::
     65                 value_type value_type;
     66         for (; begin != end; ++begin, ++dest) {
     67             new (static_cast<void*>(&*dest)) value_type(*begin);
     68         }
     69         return dest;
     70     }
     71 };
     72 
     73 // Full specialization when the src and dest types are pod && both
     74 // iterators are random access.
     75 template<>
     76 struct __uninitialized_copy<true,
     77                             random_access_iterator_tag,
     78                             random_access_iterator_tag>
     79 {
     80     template<typename _InputIterator, typename _ForwardIterator>
     81     static _ForwardIterator uninitialized_copy(_InputIterator begin,
     82                                                _InputIterator end,
     83                                                _ForwardIterator dest)
     84     {
     85         typedef typename iterator_traits<_InputIterator>::
     86                 difference_type difference_type;
     87         const difference_type len = std::distance(begin, end);
     88         const difference_type kMaxSize =
     89                 std::numeric_limits<difference_type>::max();
     90 
     91         typedef typename iterator_traits<_ForwardIterator>::
     92                 value_type value_type;
     93         const size_t kSize = sizeof(value_type);
     94 
     95         if (len > 0 &&
     96             static_cast<size_t>(kMaxSize) / kSize > static_cast<size_t>(len)) {
     97             std::memmove(static_cast<void*>(&*dest),
     98                          static_cast<const void*>(&*begin), kSize * len);
     99             return dest + len;
    100         } else {
    101             return dest;
    102         }
    103     }
    104 };
    105 
    106 // TODO: If placement new degrades to assignement for POD, we can get
    107 // rid of this one.
    108 // Bothe pod but not both random access
    109 template<> struct __uninitialized_copy<true,
    110                                        input_iterator_tag,
    111                                        forward_iterator_tag>
    112 {
    113     template<typename _InputIterator, typename _ForwardIterator>
    114     static _ForwardIterator uninitialized_copy(_InputIterator begin,
    115                                                _InputIterator end,
    116                                                _ForwardIterator dest) {
    117         for (; begin != end; ++begin, ++dest) {
    118             *dest = *begin;
    119         }
    120         return dest;
    121     }
    122 };
    123 
    124 
    125 template<typename _InputIterator, typename _ForwardIterator>
    126 inline _ForwardIterator uninitialized_copy(_InputIterator begin,
    127                                            _InputIterator end,
    128                                            _ForwardIterator dest)
    129 {
    130     typedef typename iterator_traits<_InputIterator>::value_type _ValueType1;
    131     typedef typename iterator_traits<_ForwardIterator>::value_type _ValueType2;
    132 
    133     const bool both_pod =
    134             is_pod<_ValueType1>::value && is_pod<_ValueType2>::value;
    135 
    136     return __uninitialized_copy<both_pod,
    137             typename iterator_traits<_InputIterator>::iterator_category,
    138             typename iterator_traits<_ForwardIterator>::iterator_category>::
    139             uninitialized_copy(begin, end, dest);
    140 }
    141 
    142 // TODO: replace pointers with iterator below.
    143 
    144 // uninitialized_fill is used when memory allocation and object
    145 // construction need to happen in separate steps. uninitialized_fill
    146 // creates a copy of 'obj' in the location pointed by the interator,
    147 // using the object's class copy constructor.
    148 
    149 template<bool> struct __uninitialized_fill
    150 {
    151     template<typename _ForwardIterator, typename _T>
    152     static void uninitialized_fill(_ForwardIterator *begin,
    153                                    _ForwardIterator *end,
    154                                    const _T& val)
    155     {
    156         for (; begin < end; ++begin)
    157             new (static_cast<void*>(&*begin)) _ForwardIterator(val);
    158     }
    159 };
    160 
    161 template<> struct __uninitialized_fill<true>
    162 {
    163     template<typename _ForwardIterator, typename _T>
    164     static void uninitialized_fill(_ForwardIterator *begin,
    165                                    _ForwardIterator *end,
    166                                    const _T& val)
    167     {
    168         std::fill(begin, end, val);
    169     }
    170 };
    171 
    172 // The real STL takes iterators, we take pointers for now.
    173 template<typename _ForwardIterator, typename _T>
    174 inline void uninitialized_fill(_ForwardIterator *begin,
    175                                _ForwardIterator *end,
    176                                const _T& val)
    177 {
    178     const bool pod = is_pod<_ForwardIterator>::value;
    179     return __uninitialized_fill<pod>::uninitialized_fill(begin, end, val);
    180 }
    181 
    182 }  // namespace std
    183 
    184 #endif  // ANDROID_ASTL_MEMORY__
    185