1261272Sdim// -*- C++ -*-
2261272Sdim//===-------------------------- dynarray ----------------------------------===//
3261272Sdim//
4261272Sdim//                     The LLVM Compiler Infrastructure
5261272Sdim//
6261272Sdim// This file is dual licensed under the MIT and the University of Illinois Open
7261272Sdim// Source Licenses. See LICENSE.TXT for details.
8261272Sdim//
9261272Sdim//===----------------------------------------------------------------------===//
10261272Sdim
11261272Sdim#ifndef _LIBCPP_DYNARRAY
12261272Sdim#define _LIBCPP_DYNARRAY
13261272Sdim
14261272Sdim#include <__config>
15261272Sdim#if _LIBCPP_STD_VER > 11
16261272Sdim
17261272Sdim/*
18261272Sdim    dynarray synopsis
19261272Sdim
20261272Sdimnamespace std { namespace experimental {
21261272Sdim
22261272Sdimtemplate< typename T >
23261272Sdimclass dynarray
24261272Sdim{
25261272Sdim    // types:
26261272Sdim    typedef       T                               value_type;
27261272Sdim    typedef       T&                              reference;
28261272Sdim    typedef const T&                              const_reference;
29261272Sdim    typedef       T*                              pointer;
30261272Sdim    typedef const T*                              const_pointer;
31261272Sdim    typedef       implementation-defined          iterator;
32261272Sdim    typedef       implementation-defined          const_iterator;
33261272Sdim    typedef reverse_iterator<iterator>            reverse_iterator;
34261272Sdim    typedef reverse_iterator<const_iterator>      const_reverse_iterator;
35261272Sdim    typedef size_t                                size_type;
36261272Sdim    typedef ptrdiff_t                             difference_type;
37261272Sdim
38261272Sdimpublic:
39261272Sdim    // construct/copy/destroy:
40261272Sdim    explicit dynarray(size_type c);
41261272Sdim    dynarray(size_type c, const T& v);
42261272Sdim    dynarray(const dynarray& d);
43261272Sdim    dynarray(initializer_list<T>);
44261272Sdim
45276792Sdim    template <class Alloc>
46276792Sdim      dynarray(allocator_arg_t, const Alloc& a, size_type c, const Alloc& alloc);
47276792Sdim    template <class Alloc>
48276792Sdim      dynarray(allocator_arg_t, const Alloc& a, size_type c, const T& v, const Alloc& alloc);
49276792Sdim    template <class Alloc>
50276792Sdim      dynarray(allocator_arg_t, const Alloc& a, const dynarray& d, const Alloc& alloc);
51276792Sdim    template <class Alloc>
52276792Sdim      dynarray(allocator_arg_t, const Alloc& a, initializer_list<T>, const Alloc& alloc);
53261272Sdim    dynarray& operator=(const dynarray&) = delete;
54261272Sdim    ~dynarray();
55261272Sdim
56261272Sdim    // iterators:
57261272Sdim    iterator       begin()        noexcept;
58261272Sdim    const_iterator begin()  const noexcept;
59261272Sdim    const_iterator cbegin() const noexcept;
60261272Sdim    iterator       end()          noexcept;
61261272Sdim    const_iterator end()    const noexcept;
62261272Sdim    const_iterator cend()   const noexcept;
63261272Sdim
64261272Sdim    reverse_iterator       rbegin()        noexcept;
65261272Sdim    const_reverse_iterator rbegin()  const noexcept;
66261272Sdim    const_reverse_iterator crbegin() const noexcept;
67261272Sdim    reverse_iterator       rend()          noexcept;
68261272Sdim    const_reverse_iterator rend()    const noexcept;
69261272Sdim    const_reverse_iterator crend()   const noexcept;
70261272Sdim
71261272Sdim    // capacity:
72261272Sdim    size_type size()     const noexcept;
73261272Sdim    size_type max_size() const noexcept;
74261272Sdim    bool      empty()    const noexcept;
75261272Sdim
76261272Sdim    // element access:
77261272Sdim    reference       operator[](size_type n);
78261272Sdim    const_reference operator[](size_type n) const;
79261272Sdim
80261272Sdim    reference       front();
81261272Sdim    const_reference front() const;
82261272Sdim    reference       back();
83261272Sdim    const_reference back()  const;
84261272Sdim
85261272Sdim    const_reference at(size_type n) const;
86261272Sdim    reference       at(size_type n);
87261272Sdim
88261272Sdim    // data access:
89261272Sdim    T*       data()       noexcept;
90261272Sdim    const T* data() const noexcept;
91261272Sdim
92261272Sdim    // mutating member functions:
93261272Sdim    void fill(const T& v);
94261272Sdim};
95261272Sdim
96261272Sdim}}  // std::experimental
97261272Sdim
98261272Sdim*/
99261272Sdim
100261272Sdim#include <__functional_base>
101261272Sdim#include <iterator>
102261272Sdim#include <stdexcept>
103261272Sdim#include <initializer_list>
104261272Sdim#include <new>
105261272Sdim#include <algorithm>
106261272Sdim
107288943Sdim#include <__undef___deallocate>
108288943Sdim
109261272Sdim#if defined(_LIBCPP_NO_EXCEPTIONS)
110261272Sdim    #include <cassert>
111261272Sdim#endif
112261272Sdim
113261272Sdim#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
114261272Sdim#pragma GCC system_header
115261272Sdim#endif
116261272Sdim
117261272Sdimnamespace std { namespace experimental { inline namespace __array_extensions_v1 {
118261272Sdim
119261272Sdimtemplate <class _Tp>
120261272Sdimstruct _LIBCPP_TYPE_VIS_ONLY dynarray
121261272Sdim{
122261272Sdimpublic:
123261272Sdim    // types:
124261272Sdim    typedef dynarray __self;
125261272Sdim    typedef _Tp                                   value_type;
126261272Sdim    typedef value_type&                           reference;
127261272Sdim    typedef const value_type&                     const_reference;
128261272Sdim    typedef value_type*                           iterator;
129261272Sdim    typedef const value_type*                     const_iterator;
130261272Sdim    typedef value_type*                           pointer;
131261272Sdim    typedef const value_type*                     const_pointer;
132261272Sdim    typedef size_t                                size_type;
133261272Sdim    typedef ptrdiff_t                             difference_type;
134261272Sdim    typedef std::reverse_iterator<iterator>       reverse_iterator;
135261272Sdim    typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
136261272Sdim
137261272Sdimprivate:
138261272Sdim    size_t                  __size_;
139261272Sdim    value_type *            __base_;
140300770Sdim    _LIBCPP_ALWAYS_INLINE dynarray () noexcept :  __size_(0), __base_(nullptr) {}
141261272Sdim    
142261272Sdim    static inline _LIBCPP_INLINE_VISIBILITY value_type* __allocate ( size_t count )
143261272Sdim    {
144261272Sdim        if ( numeric_limits<size_t>::max() / sizeof (value_type) <= count )
145261272Sdim        {
146261272Sdim#ifndef _LIBCPP_NO_EXCEPTIONS
147261272Sdim            throw bad_array_length();
148261272Sdim#else
149261272Sdim            assert(!"dynarray::allocation");
150261272Sdim#endif
151261272Sdim        }
152276792Sdim        return static_cast<value_type *> (_VSTD::__allocate (sizeof(value_type) * count));
153261272Sdim    }
154261272Sdim
155261272Sdim    static inline _LIBCPP_INLINE_VISIBILITY void __deallocate ( value_type* __ptr ) noexcept
156261272Sdim    {
157276792Sdim        _VSTD::__deallocate (static_cast<void *> (__ptr));
158261272Sdim    }
159261272Sdim
160261272Sdimpublic:
161261272Sdim
162261272Sdim    explicit dynarray(size_type __c);
163261272Sdim    dynarray(size_type __c, const value_type& __v);
164261272Sdim    dynarray(const dynarray& __d);
165261272Sdim    dynarray(initializer_list<value_type>);
166261272Sdim
167261272Sdim//  We're not implementing these right now.
168276792Sdim//  Updated with the resolution of LWG issue #2255
169261272Sdim//     template <typename _Alloc>
170276792Sdim//       dynarray(allocator_arg_t, const _Alloc& __alloc, size_type __c);
171261272Sdim//     template <typename _Alloc>
172276792Sdim//       dynarray(allocator_arg_t, const _Alloc& __alloc, size_type __c, const value_type& __v);
173261272Sdim//     template <typename _Alloc>
174276792Sdim//       dynarray(allocator_arg_t, const _Alloc& __alloc, const dynarray& __d);
175261272Sdim//     template <typename _Alloc>
176276792Sdim//       dynarray(allocator_arg_t, const _Alloc& __alloc, initializer_list<value_type>);
177261272Sdim
178261272Sdim    dynarray& operator=(const dynarray&) = delete;
179261272Sdim    ~dynarray();
180261272Sdim
181261272Sdim    // iterators:
182261272Sdim    inline _LIBCPP_INLINE_VISIBILITY iterator       begin()        noexcept { return iterator(data()); }
183261272Sdim    inline _LIBCPP_INLINE_VISIBILITY const_iterator begin()  const noexcept { return const_iterator(data()); }
184261272Sdim    inline _LIBCPP_INLINE_VISIBILITY const_iterator cbegin() const noexcept { return const_iterator(data()); }
185261272Sdim    inline _LIBCPP_INLINE_VISIBILITY iterator       end()          noexcept { return iterator(data() + __size_); }
186261272Sdim    inline _LIBCPP_INLINE_VISIBILITY const_iterator end()    const noexcept { return const_iterator(data() + __size_); }
187261272Sdim    inline _LIBCPP_INLINE_VISIBILITY const_iterator cend()   const noexcept { return const_iterator(data() + __size_); }
188261272Sdim
189261272Sdim    inline _LIBCPP_INLINE_VISIBILITY reverse_iterator       rbegin()        noexcept { return reverse_iterator(end()); }
190261272Sdim    inline _LIBCPP_INLINE_VISIBILITY const_reverse_iterator rbegin()  const noexcept { return const_reverse_iterator(end()); }
191261272Sdim    inline _LIBCPP_INLINE_VISIBILITY const_reverse_iterator crbegin() const noexcept { return const_reverse_iterator(end()); }
192261272Sdim    inline _LIBCPP_INLINE_VISIBILITY reverse_iterator       rend()          noexcept { return reverse_iterator(begin()); }
193261272Sdim    inline _LIBCPP_INLINE_VISIBILITY const_reverse_iterator rend()    const noexcept { return const_reverse_iterator(begin()); }
194261272Sdim    inline _LIBCPP_INLINE_VISIBILITY const_reverse_iterator crend()   const noexcept { return const_reverse_iterator(begin()); }
195261272Sdim
196261272Sdim    // capacity:
197261272Sdim    inline _LIBCPP_INLINE_VISIBILITY size_type size()     const noexcept { return __size_; }
198261272Sdim    inline _LIBCPP_INLINE_VISIBILITY size_type max_size() const noexcept { return __size_; }
199261272Sdim    inline _LIBCPP_INLINE_VISIBILITY bool      empty()    const noexcept { return __size_ == 0; }
200261272Sdim
201261272Sdim    // element access:
202261272Sdim    inline _LIBCPP_INLINE_VISIBILITY reference       operator[](size_type __n)       { return data()[__n]; }
203261272Sdim    inline _LIBCPP_INLINE_VISIBILITY const_reference operator[](size_type __n) const { return data()[__n]; }
204261272Sdim
205261272Sdim    inline _LIBCPP_INLINE_VISIBILITY reference       front()       { return data()[0]; }
206261272Sdim    inline _LIBCPP_INLINE_VISIBILITY const_reference front() const { return data()[0]; }
207261272Sdim    inline _LIBCPP_INLINE_VISIBILITY reference       back()        { return data()[__size_-1]; }
208261272Sdim    inline _LIBCPP_INLINE_VISIBILITY const_reference back()  const { return data()[__size_-1]; }
209261272Sdim
210261272Sdim    inline _LIBCPP_INLINE_VISIBILITY const_reference at(size_type __n) const;
211261272Sdim    inline _LIBCPP_INLINE_VISIBILITY reference       at(size_type __n);
212261272Sdim
213261272Sdim    // data access:
214261272Sdim    inline _LIBCPP_INLINE_VISIBILITY _Tp*       data()       noexcept { return __base_; }
215261272Sdim    inline _LIBCPP_INLINE_VISIBILITY const _Tp* data() const noexcept { return __base_; }
216261272Sdim
217261272Sdim    // mutating member functions:
218261272Sdim    inline _LIBCPP_INLINE_VISIBILITY void fill(const value_type& __v) { fill_n(begin(), __size_, __v); }
219261272Sdim};
220261272Sdim
221261272Sdimtemplate <class _Tp>
222261272Sdiminline _LIBCPP_INLINE_VISIBILITY
223261272Sdimdynarray<_Tp>::dynarray(size_type __c) : dynarray ()
224261272Sdim{
225261272Sdim    __base_ = __allocate (__c);
226261272Sdim    value_type *__data = data ();
227261272Sdim    for ( __size_ = 0; __size_ < __c; ++__size_, ++__data )
228261272Sdim        ::new (__data) value_type;
229261272Sdim}
230261272Sdim
231261272Sdimtemplate <class _Tp>
232261272Sdiminline _LIBCPP_INLINE_VISIBILITY
233261272Sdimdynarray<_Tp>::dynarray(size_type __c, const value_type& __v) : dynarray ()
234261272Sdim{
235261272Sdim    __base_ = __allocate (__c);
236261272Sdim    value_type *__data = data ();
237261272Sdim    for ( __size_ = 0; __size_ < __c; ++__size_, ++__data )
238261272Sdim        ::new (__data) value_type (__v);
239261272Sdim}
240261272Sdim
241261272Sdimtemplate <class _Tp>
242261272Sdiminline _LIBCPP_INLINE_VISIBILITY
243261272Sdimdynarray<_Tp>::dynarray(initializer_list<value_type> __il) : dynarray ()
244261272Sdim{
245261272Sdim    size_t sz = __il.size();
246261272Sdim    __base_ = __allocate (sz);
247261272Sdim    value_type *__data = data ();
248261272Sdim    auto src = __il.begin();
249261272Sdim    for ( __size_ = 0; __size_ < sz; ++__size_, ++__data, ++src )
250261272Sdim        ::new (__data) value_type (*src);
251261272Sdim}
252261272Sdim
253261272Sdimtemplate <class _Tp>
254261272Sdiminline _LIBCPP_INLINE_VISIBILITY
255261272Sdimdynarray<_Tp>::dynarray(const dynarray& __d) : dynarray ()
256261272Sdim{
257261272Sdim    size_t sz = __d.size();
258261272Sdim    __base_ = __allocate (sz);
259261272Sdim    value_type *__data = data ();
260261272Sdim    auto src = __d.begin();
261261272Sdim    for ( __size_ = 0; __size_ < sz; ++__size_, ++__data, ++src )
262261272Sdim        ::new (__data) value_type (*src);
263261272Sdim}
264261272Sdim
265261272Sdimtemplate <class _Tp>
266261272Sdiminline _LIBCPP_INLINE_VISIBILITY
267261272Sdimdynarray<_Tp>::~dynarray()
268261272Sdim{ 
269261272Sdim    value_type *__data = data () + __size_;
270261272Sdim    for ( size_t i = 0; i < __size_; ++i )
271261272Sdim        (--__data)->value_type::~value_type();
272261272Sdim    __deallocate ( __base_ );
273261272Sdim}
274261272Sdim
275261272Sdimtemplate <class _Tp>
276261272Sdiminline _LIBCPP_INLINE_VISIBILITY
277261272Sdimtypename dynarray<_Tp>::reference
278261272Sdimdynarray<_Tp>::at(size_type __n)
279261272Sdim{
280261272Sdim    if (__n >= __size_)
281261272Sdim    {
282261272Sdim#ifndef _LIBCPP_NO_EXCEPTIONS
283261272Sdim        throw out_of_range("dynarray::at");
284261272Sdim#else
285261272Sdim        assert(!"dynarray::at out_of_range");
286261272Sdim#endif
287261272Sdim    }
288261272Sdim    return data()[__n];
289261272Sdim}
290261272Sdim
291261272Sdimtemplate <class _Tp>
292261272Sdiminline _LIBCPP_INLINE_VISIBILITY
293261272Sdimtypename dynarray<_Tp>::const_reference
294261272Sdimdynarray<_Tp>::at(size_type __n) const
295261272Sdim{
296261272Sdim    if (__n >= __size_)
297261272Sdim    {
298261272Sdim#ifndef _LIBCPP_NO_EXCEPTIONS
299261272Sdim        throw out_of_range("dynarray::at");
300261272Sdim#else
301261272Sdim        assert(!"dynarray::at out_of_range");
302261272Sdim#endif
303261272Sdim    }
304261272Sdim    return data()[__n];
305261272Sdim}
306261272Sdim
307261272Sdim}}}
308261272Sdim
309261272Sdim
310261272Sdim_LIBCPP_BEGIN_NAMESPACE_STD
311261272Sdimtemplate <class _Tp, class _Alloc>
312261272Sdimstruct _LIBCPP_TYPE_VIS_ONLY uses_allocator<std::experimental::dynarray<_Tp>, _Alloc> : true_type {};
313261272Sdim_LIBCPP_END_NAMESPACE_STD
314261272Sdim
315261272Sdim#endif  // if _LIBCPP_STD_VER > 11 
316261272Sdim#endif  // _LIBCPP_DYNARRAY
317