1// Profiling vector implementation -*- C++ -*-
2
3// Copyright (C) 2009, 2010, 2011 Free Software Foundation, Inc.
4//
5// This file is part of the GNU ISO C++ Library.  This library is free
6// software; you can redistribute it and/or modify it under the
7// terms of the GNU General Public License as published by the
8// Free Software Foundation; either version 3, or (at your option)
9// any later version.
10//
11// This library is distributed in the hope that it will be useful,
12// but WITHOUT ANY WARRANTY; without even the implied warranty of
13// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14// GNU General Public License for more details.
15
16// Under Section 7 of GPL version 3, you are granted additional
17// permissions described in the GCC Runtime Library Exception, version
18// 3.1, as published by the Free Software Foundation.
19
20// You should have received a copy of the GNU General Public License along
21// with this library; see the file COPYING3.  If not see
22// <http://www.gnu.org/licenses/>.
23
24/** @file profile/vector
25 *  This file is a GNU profile extension to the Standard C++ Library.
26 */
27
28#ifndef _GLIBCXX_PROFILE_VECTOR
29#define _GLIBCXX_PROFILE_VECTOR 1
30
31#include <vector>
32#include <utility>
33#include <profile/base.h>
34#include <profile/iterator_tracker.h>
35
36namespace std _GLIBCXX_VISIBILITY(default)
37{
38namespace __profile
39{
40  template<typename _Tp,
41	   typename _Allocator = std::allocator<_Tp> >
42    class vector
43    : public _GLIBCXX_STD_C::vector<_Tp, _Allocator>
44    {
45      typedef _GLIBCXX_STD_C::vector<_Tp, _Allocator> _Base;
46
47#ifdef __GXX_EXPERIMENTAL_CXX0X__
48      typedef __gnu_cxx::__alloc_traits<_Allocator>  _Alloc_traits;
49#endif
50
51    public:
52      typedef typename _Base::reference             reference;
53      typedef typename _Base::const_reference       const_reference;
54
55      typedef __iterator_tracker<typename _Base::iterator, vector>
56                                                    iterator;
57      typedef __iterator_tracker<typename _Base::const_iterator, vector>
58				                    const_iterator;
59
60      typedef typename _Base::size_type             size_type;
61      typedef typename _Base::difference_type       difference_type;
62
63      typedef _Tp				    value_type;
64      typedef _Allocator			    allocator_type;
65      typedef typename _Base::pointer               pointer;
66      typedef typename _Base::const_pointer         const_pointer;
67      typedef std::reverse_iterator<iterator>       reverse_iterator;
68      typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
69
70      _Base&
71      _M_base() _GLIBCXX_NOEXCEPT { return *this; }
72
73      const _Base&
74      _M_base() const _GLIBCXX_NOEXCEPT { return *this; }
75
76      // 23.2.4.1 construct/copy/destroy:
77      explicit
78      vector(const _Allocator& __a = _Allocator())
79      : _Base(__a)
80      {
81        __profcxx_vector_construct(this, this->capacity());
82        __profcxx_vector_construct2(this);
83      }
84
85#ifdef __GXX_EXPERIMENTAL_CXX0X__
86      explicit
87      vector(size_type __n)
88      : _Base(__n)
89      {
90        __profcxx_vector_construct(this, this->capacity());
91        __profcxx_vector_construct2(this);
92      }
93
94      vector(size_type __n, const _Tp& __value,
95	     const _Allocator& __a = _Allocator())
96      :  _Base(__n, __value, __a)
97      {
98        __profcxx_vector_construct(this, this->capacity());
99        __profcxx_vector_construct2(this);
100      }
101#else
102      explicit
103      vector(size_type __n, const _Tp& __value = _Tp(),
104	     const _Allocator& __a = _Allocator())
105      : _Base(__n, __value, __a)
106      {
107        __profcxx_vector_construct(this, this->capacity());
108        __profcxx_vector_construct2(this);
109      }
110#endif
111
112      template<class _InputIterator>
113        vector(_InputIterator __first, _InputIterator __last,
114	       const _Allocator& __a = _Allocator())
115	: _Base(__first, __last, __a)
116        {
117	  __profcxx_vector_construct(this, this->capacity());
118	  __profcxx_vector_construct2(this);
119	}
120
121      vector(const vector& __x)
122      : _Base(__x)
123      {
124        __profcxx_vector_construct(this, this->capacity());
125        __profcxx_vector_construct2(this);
126      }
127
128      /// Construction from a release-mode vector
129      vector(const _Base& __x)
130      : _Base(__x)
131      {
132        __profcxx_vector_construct(this, this->capacity());
133        __profcxx_vector_construct2(this);
134      }
135
136#ifdef __GXX_EXPERIMENTAL_CXX0X__
137      vector(vector&& __x) noexcept
138      : _Base(std::move(__x))
139      {
140        __profcxx_vector_construct(this, this->capacity());
141        __profcxx_vector_construct2(this);
142      }
143
144      vector(const _Base& __x, const _Allocator& __a)
145      : _Base(__x)
146      {
147        __profcxx_vector_construct(this, this->capacity());
148        __profcxx_vector_construct2(this);
149      }
150
151      vector(vector&& __x, const _Allocator& __a) noexcept
152      : _Base(std::move(__x), __a)
153      {
154        __profcxx_vector_construct(this, this->capacity());
155        __profcxx_vector_construct2(this);
156      }
157
158      vector(initializer_list<value_type> __l,
159	     const allocator_type& __a = allocator_type())
160      : _Base(__l, __a) { }
161#endif
162
163      ~vector() _GLIBCXX_NOEXCEPT
164      {
165        __profcxx_vector_destruct(this, this->capacity(), this->size());
166        __profcxx_vector_destruct2(this);
167      }
168
169      vector&
170      operator=(const vector& __x)
171      {
172        static_cast<_Base&>(*this) = __x;
173        return *this;
174      }
175
176#ifdef __GXX_EXPERIMENTAL_CXX0X__
177      vector&
178      operator=(vector&& __x) noexcept(_Alloc_traits::_S_nothrow_move())
179      {
180	__profcxx_vector_destruct(this, this->capacity(), this->size());
181	__profcxx_vector_destruct2(this);
182	static_cast<_Base&>(*this) = std::move(__x);
183	return *this;
184      }
185
186      vector&
187      operator=(initializer_list<value_type> __l)
188      {
189	static_cast<_Base&>(*this) = __l;
190	return *this;
191      }
192#endif
193
194      using _Base::assign;
195      using _Base::get_allocator;
196
197
198      // iterators:
199      iterator
200      begin() _GLIBCXX_NOEXCEPT
201      { return iterator(_Base::begin(), this); }
202
203      const_iterator
204      begin() const _GLIBCXX_NOEXCEPT
205      { return const_iterator(_Base::begin(), this); }
206
207      iterator
208      end() _GLIBCXX_NOEXCEPT
209      { return iterator(_Base::end(), this); }
210
211      const_iterator
212      end() const _GLIBCXX_NOEXCEPT
213      { return const_iterator(_Base::end(), this); }
214
215      reverse_iterator
216      rbegin() _GLIBCXX_NOEXCEPT
217      { return reverse_iterator(end()); }
218
219      const_reverse_iterator
220      rbegin() const _GLIBCXX_NOEXCEPT
221      { return const_reverse_iterator(end()); }
222
223      reverse_iterator
224      rend() _GLIBCXX_NOEXCEPT
225      { return reverse_iterator(begin()); }
226
227      const_reverse_iterator
228      rend() const _GLIBCXX_NOEXCEPT
229      { return const_reverse_iterator(begin()); }
230
231#ifdef __GXX_EXPERIMENTAL_CXX0X__
232      const_iterator
233      cbegin() const noexcept
234      { return const_iterator(_Base::begin(), this); }
235
236      const_iterator
237      cend() const noexcept
238      { return const_iterator(_Base::end(), this); }
239
240      const_reverse_iterator
241      crbegin() const noexcept
242      { return const_reverse_iterator(end()); }
243
244      const_reverse_iterator
245      crend() const noexcept
246      { return const_reverse_iterator(begin()); }
247#endif
248
249      // 23.2.4.2 capacity:
250      using _Base::size;
251      using _Base::max_size;
252
253#ifdef __GXX_EXPERIMENTAL_CXX0X__
254      void
255      resize(size_type __sz)
256      {
257        __profcxx_vector_invalid_operator(this);
258        _M_profile_resize(this, this->capacity(), __sz);
259        _Base::resize(__sz);
260      }
261
262      void
263      resize(size_type __sz, const _Tp& __c)
264      {
265        __profcxx_vector_invalid_operator(this);
266        _M_profile_resize(this, this->capacity(), __sz);
267        _Base::resize(__sz, __c);
268      }
269#else
270      void
271      resize(size_type __sz, _Tp __c = _Tp())
272      {
273        __profcxx_vector_invalid_operator(this);
274        _M_profile_resize(this, this->capacity(), __sz);
275        _Base::resize(__sz, __c);
276      }
277#endif
278
279#ifdef __GXX_EXPERIMENTAL_CXX0X__
280      using _Base::shrink_to_fit;
281#endif
282
283      using _Base::empty;
284
285      // element access:
286      reference
287      operator[](size_type __n)
288      {
289        __profcxx_vector_invalid_operator(this);
290        return _M_base()[__n];
291      }
292      const_reference
293      operator[](size_type __n) const
294      {
295        __profcxx_vector_invalid_operator(this);
296        return _M_base()[__n];
297      }
298
299      using _Base::at;
300
301      reference
302      front()
303      {
304        return _Base::front();
305      }
306
307      const_reference
308      front() const
309      {
310	return _Base::front();
311      }
312
313      reference
314      back()
315      {
316	return _Base::back();
317      }
318
319      const_reference
320      back() const
321      {
322	return _Base::back();
323      }
324
325      // _GLIBCXX_RESOLVE_LIB_DEFECTS
326      // DR 464. Suggestion for new member functions in standard containers.
327      using _Base::data;
328
329      // 23.2.4.3 modifiers:
330      void
331      push_back(const _Tp& __x)
332      {
333        size_type __old_size = this->capacity();
334	_Base::push_back(__x);
335        _M_profile_resize(this, __old_size, this->capacity());
336      }
337
338#ifdef __GXX_EXPERIMENTAL_CXX0X__
339      void
340      push_back(_Tp&& __x)
341      {
342        size_type __old_size = this->capacity();
343        _Base::push_back(std::move(__x));
344        _M_profile_resize(this, __old_size, this->capacity());
345      }
346
347#endif
348
349      iterator
350      insert(iterator __position, const _Tp& __x)
351      {
352        __profcxx_vector_insert(this, __position.base() - _Base::begin(),
353                                this->size());
354        size_type __old_size = this->capacity();
355	typename _Base::iterator __res = _Base::insert(__position.base(), __x);
356        _M_profile_resize(this, __old_size, this->capacity());
357	return iterator(__res, this);
358      }
359
360#ifdef __GXX_EXPERIMENTAL_CXX0X__
361      iterator
362      insert(iterator __position, _Tp&& __x)
363      {
364        __profcxx_vector_insert(this, __position.base() - _Base::begin(),
365                                this->size());
366        size_type __old_size = this->capacity();
367	typename _Base::iterator __res = _Base::insert(__position.base(), __x);
368        _M_profile_resize(this, __old_size, this->capacity());
369	return iterator(__res, this);
370      }
371
372      void
373      insert(iterator __position, initializer_list<value_type> __l)
374      { this->insert(__position, __l.begin(), __l.end()); }
375#endif
376
377#ifdef __GXX_EXPERIMENTAL_CXX0X__
378      void
379      swap(vector&& __x)
380      {
381        _Base::swap(__x);
382      }
383#endif
384
385      void
386      swap(vector& __x)
387#ifdef __GXX_EXPERIMENTAL_CXX0X__
388			noexcept(_Alloc_traits::_S_nothrow_swap())
389#endif
390      {
391        _Base::swap(__x);
392      }
393
394      void
395      insert(iterator __position, size_type __n, const _Tp& __x)
396      {
397        __profcxx_vector_insert(this, __position.base() - _Base::begin(),
398                                this->size());
399        size_type __old_size = this->capacity();
400        _Base::insert(__position, __n, __x);
401        _M_profile_resize(this, __old_size, this->capacity());
402      }
403
404      template<class _InputIterator>
405      void
406      insert(iterator __position,
407             _InputIterator __first, _InputIterator __last)
408      {
409        __profcxx_vector_insert(this, __position.base()-_Base::begin(),
410                                this->size());
411        size_type __old_size = this->capacity();
412        _Base::insert(__position, __first, __last);
413        _M_profile_resize(this, __old_size, this->capacity());
414      }
415
416
417      iterator
418      erase(iterator __position)
419      {
420	typename _Base::iterator __res = _Base::erase(__position.base());
421	return iterator(__res, this);
422      }
423
424      iterator
425      erase(iterator __first, iterator __last)
426      {
427	// _GLIBCXX_RESOLVE_LIB_DEFECTS
428	// 151. can't currently clear() empty container
429	typename _Base::iterator __res = _Base::erase(__first.base(),
430                                                      __last.base());
431	return iterator(__res, this);
432      }
433
434      void
435      clear() _GLIBCXX_NOEXCEPT
436      {
437        __profcxx_vector_destruct(this, this->capacity(), this->size());
438        __profcxx_vector_destruct2(this);
439        _Base::clear();
440      }
441
442      inline void _M_profile_find() const
443      {
444        __profcxx_vector_find(this, size());
445      }
446
447      inline void _M_profile_iterate(int __rewind = 0) const
448      {
449        __profcxx_vector_iterate(this);
450      }
451
452    private:
453      void _M_profile_resize(void* obj, size_type __old_size,
454                             size_type __new_size)
455      {
456        if (__old_size < __new_size) {
457          __profcxx_vector_resize(this, this->size(), __new_size);
458          __profcxx_vector_resize2(this, this->size(), __new_size);
459        }
460      }
461    };
462
463  template<typename _Tp, typename _Alloc>
464    inline bool
465    operator==(const vector<_Tp, _Alloc>& __lhs,
466           const vector<_Tp, _Alloc>& __rhs)
467    { return __lhs._M_base() == __rhs._M_base(); }
468
469  template<typename _Tp, typename _Alloc>
470    inline bool
471    operator!=(const vector<_Tp, _Alloc>& __lhs,
472           const vector<_Tp, _Alloc>& __rhs)
473    { return __lhs._M_base() != __rhs._M_base(); }
474
475  template<typename _Tp, typename _Alloc>
476    inline bool
477    operator<(const vector<_Tp, _Alloc>& __lhs,
478          const vector<_Tp, _Alloc>& __rhs)
479    { return __lhs._M_base() < __rhs._M_base(); }
480
481  template<typename _Tp, typename _Alloc>
482    inline bool
483    operator<=(const vector<_Tp, _Alloc>& __lhs,
484           const vector<_Tp, _Alloc>& __rhs)
485    { return __lhs._M_base() <= __rhs._M_base(); }
486
487  template<typename _Tp, typename _Alloc>
488    inline bool
489    operator>=(const vector<_Tp, _Alloc>& __lhs,
490           const vector<_Tp, _Alloc>& __rhs)
491    { return __lhs._M_base() >= __rhs._M_base(); }
492
493  template<typename _Tp, typename _Alloc>
494    inline bool
495    operator>(const vector<_Tp, _Alloc>& __lhs,
496          const vector<_Tp, _Alloc>& __rhs)
497    { return __lhs._M_base() > __rhs._M_base(); }
498
499  template<typename _Tp, typename _Alloc>
500    inline void
501    swap(vector<_Tp, _Alloc>& __lhs, vector<_Tp, _Alloc>& __rhs)
502    { __lhs.swap(__rhs); }
503
504#ifdef __GXX_EXPERIMENTAL_CXX0X__
505  template<typename _Tp, typename _Alloc>
506    inline void
507    swap(vector<_Tp, _Alloc>&& __lhs, vector<_Tp, _Alloc>& __rhs)
508    { __lhs.swap(__rhs); }
509
510  template<typename _Tp, typename _Alloc>
511    inline void
512    swap(vector<_Tp, _Alloc>& __lhs, vector<_Tp, _Alloc>&& __rhs)
513    { __lhs.swap(__rhs); }
514#endif
515
516} // namespace __profile
517
518#ifdef __GXX_EXPERIMENTAL_CXX0X__
519  // DR 1182.
520  /// std::hash specialization for vector<bool>.
521  template<typename _Alloc>
522    struct hash<__profile::vector<bool, _Alloc>>
523    : public __hash_base<size_t, __profile::vector<bool, _Alloc>>
524    {
525      size_t
526      operator()(const __profile::vector<bool, _Alloc>& __b) const noexcept
527      { return std::hash<_GLIBCXX_STD_C::vector<bool, _Alloc>>()
528	  (__b._M_base()); }
529    };
530#endif
531
532} // namespace std
533
534#endif
535