memory revision fd56a38d5dcb569b146634bb22c5d9cb1e138e3f
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
38#if defined(_InputIterator) || defined(_ForwardIterator)
39#error "_InputIterator or _ForwardIterator are already defined."
40#endif
41
42namespace std {
43
44// uninitialized_copy is used when memory allocation and object
45// construction need to happen in separate steps. For each instance in
46// the input range a copy is created and placed in the corresponding
47// memory pointed by dest.
48// If the input range is made of pod instances, uninitialized_copy
49// degrades to a memmove call.
50
51template<bool> struct __uninitialized_copy
52{
53    template<typename _InputIterator, typename _ForwardIterator>
54    static _ForwardIterator *uninitialized_copy(const _InputIterator *begin,
55                                                const _InputIterator *end,
56                                                _ForwardIterator *dest)
57    {
58        _ForwardIterator *result = dest;
59        for (; begin < end; ++begin, ++dest)
60            new (static_cast<void*>(dest)) _ForwardIterator(*begin);
61        return result;
62    }
63};
64
65template<> struct __uninitialized_copy<true>
66{
67    template<typename _InputIterator, typename _ForwardIterator>
68    static _ForwardIterator *uninitialized_copy(const _InputIterator *begin,
69                                                const _InputIterator *end,
70                                                _ForwardIterator *dest)
71    {
72        const ptrdiff_t len = end - begin;
73        const size_t kMaxSizeT = ~((size_t)0);
74        const size_t kSize = sizeof(_InputIterator);
75
76        if (len > 0 && kMaxSizeT / kSize > static_cast<size_t>(len))
77        {
78            std::memmove(static_cast<void*>(dest),
79                         static_cast<const void*>(begin), kSize * len);
80        }
81        return dest;
82    }
83};
84
85// The real STL takes iterators, we take pointers for now.
86template<typename _InputIterator, typename _ForwardIterator>
87inline _ForwardIterator* uninitialized_copy(const _InputIterator *begin,
88                                            const _InputIterator *end,
89                                            _ForwardIterator *dest)
90{
91    const bool both_pod =
92            is_pod<_InputIterator>::value && is_pod<_ForwardIterator>::value;
93    return __uninitialized_copy<both_pod>::uninitialized_copy(begin, end, dest);
94}
95
96// uninitialized_fill is used when memory allocation and object
97// construction need to happen in separate steps. uninitialized_fill
98// creates a copy of 'obj' in the location pointed by the interator,
99// using the object's class copy constructor.
100
101template<bool> struct __uninitialized_fill
102{
103    template<typename _ForwardIterator, typename _T>
104    static void uninitialized_fill(_ForwardIterator *begin,
105                                   _ForwardIterator *end,
106                                   const _T& val)
107    {
108        for (; begin < end; ++begin)
109            new (static_cast<void*>(begin)) _ForwardIterator(val);
110    }
111};
112
113template<> struct __uninitialized_fill<true>
114{
115    template<typename _ForwardIterator, typename _T>
116    static void uninitialized_fill(_ForwardIterator *begin,
117                                   _ForwardIterator *end,
118                                   const _T& val)
119    {
120        std::fill(begin, end, val);
121    }
122};
123
124// The real STL takes iterators, we take pointers for now.
125template<typename _ForwardIterator, typename _T>
126inline void uninitialized_fill(_ForwardIterator *begin,
127                               _ForwardIterator *end,
128                               const _T& val)
129{
130    const bool pod = is_pod<_ForwardIterator>::value;
131    return __uninitialized_fill<pod>::uninitialized_fill(begin, end, val);
132}
133
134}  // namespace std
135
136#endif  // ANDROID_ASTL_MEMORY__
137