aboutsummaryrefslogtreecommitdiff
path: root/libstdc++/stl/deque.h
diff options
context:
space:
mode:
Diffstat (limited to 'libstdc++/stl/deque.h')
-rw-r--r--libstdc++/stl/deque.h1452
1 files changed, 1452 insertions, 0 deletions
diff --git a/libstdc++/stl/deque.h b/libstdc++/stl/deque.h
new file mode 100644
index 00000000000..6685abffe7c
--- /dev/null
+++ b/libstdc++/stl/deque.h
@@ -0,0 +1,1452 @@
+/*
+ *
+ * Copyright (c) 1994
+ * Hewlett-Packard Company
+ *
+ * Permission to use, copy, modify, distribute and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appear in all copies and
+ * that both that copyright notice and this permission notice appear
+ * in supporting documentation. Hewlett-Packard Company makes no
+ * representations about the suitability of this software for any
+ * purpose. It is provided "as is" without express or implied warranty.
+ *
+ *
+ * Copyright (c) 1997
+ * Silicon Graphics Computer Systems, Inc.
+ *
+ * Permission to use, copy, modify, distribute and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appear in all copies and
+ * that both that copyright notice and this permission notice appear
+ * in supporting documentation. Silicon Graphics makes no
+ * representations about the suitability of this software for any
+ * purpose. It is provided "as is" without express or implied warranty.
+ */
+
+#ifndef __SGI_STL_DEQUE_H
+#define __SGI_STL_DEQUE_H
+
+/* Class invariants:
+ * For any nonsingular iterator i:
+ * i.node is the address of an element in the map array. The
+ * contents of i.node is a pointer to the beginning of a node.
+ * i.first == *(i.node)
+ * i.last == i.first + node_size
+ * i.cur is a pointer in the range [i.first, i.last). NOTE:
+ * the implication of this is that i.cur is always a dereferenceable
+ * pointer, even if i is a past-the-end iterator.
+ * Start and Finish are always nonsingular iterators. NOTE: this means
+ * that an empty deque must have one node, and that a deque
+ * with N elements, where N is the buffer size, must have two nodes.
+ * For every node other than start.node and finish.node, every element
+ * in the node is an initialized object. If start.node == finish.node,
+ * then [start.cur, finish.cur) are initialized objects, and
+ * the elements outside that range are uninitialized storage. Otherwise,
+ * [start.cur, start.last) and [finish.first, finish.cur) are initialized
+ * objects, and [start.first, start.cur) and [finish.cur, finish.last)
+ * are uninitialized storage.
+ * [map, map + map_size) is a valid, non-empty range.
+ * [start.node, finish.node] is a valid range contained within
+ * [map, map + map_size).
+ * A pointer in the range [map, map + map_size) points to an allocated
+ * node if and only if the pointer is in the range [start.node, finish.node].
+ */
+
+
+/*
+ * In previous versions of deque, node_size was fixed by the
+ * implementation. In this version, however, users can select
+ * the node size. Deque has three template parameters; the third,
+ * a number of type size_t, is the number of elements per node.
+ * If the third template parameter is 0 (which is the default),
+ * then deque will use a default node size.
+ *
+ * The only reason for using an alternate node size is if your application
+ * requires a different performance tradeoff than the default. If,
+ * for example, your program contains many deques each of which contains
+ * only a few elements, then you might want to save memory (possibly
+ * by sacrificing some speed) by using smaller nodes.
+ *
+ * Unfortunately, some compilers have trouble with non-type template
+ * parameters; stl_config.h defines __STL_NON_TYPE_TMPL_PARAM_BUG if
+ * that is the case. If your compiler is one of them, then you will
+ * not be able to use alternate node sizes; you will have to use the
+ * default value.
+ */
+
+#include <stddef.h>
+#include <algobase.h>
+#include <alloc.h>
+
+// Note: this function is simply a kludge to work around several compilers'
+// bugs in handling constant expressions.
+inline size_t __deque_buf_size(size_t n, size_t sz)
+{
+ return n != 0 ? n : (sz < 512 ? size_t(512 / sz) : size_t(1));
+}
+
+#ifndef __STL_NON_TYPE_TMPL_PARAM_BUG
+template <class T, class Ref, size_t BufSiz>
+struct __deque_iterator {
+ typedef __deque_iterator<T, T&, BufSiz> iterator;
+ typedef __deque_iterator<T, const T&, BufSiz> const_iterator;
+ static size_t buffer_size() {return __deque_buf_size(BufSiz, sizeof(T)); }
+#else /* __STL_NON_TYPE_TMPL_PARAM_BUG */
+template <class T, class Ref>
+struct __deque_iterator {
+ typedef __deque_iterator<T, T&> iterator;
+ typedef __deque_iterator<T, const T&> const_iterator;
+ static size_t buffer_size() {return __deque_buf_size(0, sizeof(T)); }
+#endif
+
+ typedef random_access_iterator_tag iterator_category;
+ typedef T value_type;
+ typedef value_type* pointer;
+ typedef value_type& reference;
+ typedef const value_type& const_reference;
+ typedef size_t size_type;
+ typedef ptrdiff_t difference_type;
+ typedef pointer* map_pointer;
+
+ typedef __deque_iterator self;
+
+ pointer cur;
+ pointer first;
+ pointer last;
+ map_pointer node;
+
+ __deque_iterator(pointer x, map_pointer y)
+ : cur(x), first(*y), last(*y + buffer_size()), node(y) {}
+ __deque_iterator() : cur(0), first(0), last(0), node(0) {}
+ __deque_iterator(const iterator& x)
+ : cur(x.cur), first(x.first), last(x.last), node(x.node) {}
+
+ Ref operator*() const { return *cur; }
+
+ difference_type operator-(const self& x) const {
+ return buffer_size() * (node - x.node - 1) +
+ (cur - first) + (x.last - x.cur);
+ }
+
+ self& operator++() {
+ ++cur;
+ if (cur == last) {
+ set_node(node + 1);
+ cur = first;
+ }
+ return *this;
+ }
+ self operator++(int) {
+ self tmp = *this;
+ ++*this;
+ return tmp;
+ }
+
+ self& operator--() {
+ if (cur == first) {
+ set_node(node - 1);
+ cur = last;
+ }
+ --cur;
+ return *this;
+ }
+ self operator--(int) {
+ self tmp = *this;
+ --*this;
+ return tmp;
+ }
+
+ self& operator+=(difference_type n) {
+ difference_type offset = n + (cur - first);
+ if (offset >= 0 && offset < buffer_size())
+ cur += n;
+ else {
+ difference_type node_offset =
+ offset > 0 ? offset / buffer_size()
+ : -difference_type((-offset - 1) / buffer_size()) - 1;
+ set_node(node + node_offset);
+ cur = first + (offset - node_offset * buffer_size());
+ }
+ return *this;
+ }
+
+ self operator+(difference_type n) const {
+ self tmp = *this;
+ return tmp += n;
+ }
+
+ self& operator-=(difference_type n) { return *this += -n; }
+
+ self operator-(difference_type n) const {
+ self tmp = *this;
+ return tmp -= n;
+ }
+
+ Ref operator[](difference_type n) const { return *(*this + n); }
+
+ bool operator==(const self& x) const { return cur == x.cur; }
+ bool operator!=(const self& x) const { return !(*this == x); }
+ bool operator<(const self& x) const {
+ return (node == x.node) ? (cur < x.cur) : (node < x.node);
+ }
+
+ void set_node(map_pointer new_node) {
+ node = new_node;
+ first = *new_node;
+ last = first + buffer_size();
+ }
+};
+
+#ifndef __STL_NON_TYPE_TMPL_PARAM_BUG
+
+template <class T, class Ref, size_t BufSiz>
+inline random_access_iterator_tag
+iterator_category(const __deque_iterator<T, Ref, BufSiz>&) {
+ return random_access_iterator_tag();
+}
+
+template <class T, class Ref, size_t BufSiz>
+inline T* value_type(const __deque_iterator<T, Ref, BufSiz>&) { return 0; }
+
+template <class T, class Ref, size_t BufSiz>
+inline ptrdiff_t* distance_type(const __deque_iterator<T, Ref, BufSiz>&) {
+ return 0;
+}
+
+#else /* __STL_NON_TYPE_TMPL_PARAM_BUG */
+
+template <class T, class Ref>
+inline random_access_iterator_tag
+iterator_category(const __deque_iterator<T, Ref>&) {
+ return random_access_iterator_tag();
+}
+
+template <class T, class Ref>
+inline T* value_type(const __deque_iterator<T, Ref>&) { return 0; }
+
+template <class T, class Ref>
+inline ptrdiff_t* distance_type(const __deque_iterator<T, Ref>&) {
+ return 0;
+}
+
+#endif /* __STL_NON_TYPE_TMPL_PARAM_BUG */
+
+
+// See __deque_buf_size(). The only reason that the default value is 0
+// is as a workaround for bugs in the way that some compilers handle
+// constant expressions.
+template <class T, class Alloc = alloc, size_t BufSiz = 0>
+class deque {
+public: // Basic types
+ typedef T value_type;
+ typedef value_type* pointer;
+ typedef value_type& reference;
+ typedef const value_type& const_reference;
+ typedef size_t size_type;
+ typedef ptrdiff_t difference_type;
+
+public: // Iterators
+#ifndef __STL_NON_TYPE_TMPL_PARAM_BUG
+ typedef __deque_iterator<value_type, reference, BufSiz> iterator;
+ typedef __deque_iterator<value_type, const_reference, BufSiz> const_iterator;
+#else /* __STL_NON_TYPE_TMPL_PARAM_BUG */
+ typedef __deque_iterator<value_type, reference> iterator;
+ typedef __deque_iterator<value_type, const_reference> const_iterator;
+#endif /* __STL_NON_TYPE_TMPL_PARAM_BUG */
+ typedef reverse_iterator<const_iterator, value_type, const_reference,
+ difference_type>
+ const_reverse_iterator;
+ typedef reverse_iterator<iterator, value_type, reference, difference_type>
+ reverse_iterator;
+
+protected: // Internal typedefs
+ typedef pointer* map_pointer;
+ typedef simple_alloc<value_type, Alloc> data_allocator;
+ typedef simple_alloc<pointer, Alloc> map_allocator;
+
+ static size_type buffer_size() {
+ return __deque_buf_size(BufSiz, sizeof(value_type));
+ }
+ static size_type initial_map_size() { return 8; }
+
+protected: // Data members
+ iterator start;
+ iterator finish;
+
+ map_pointer map;
+ size_type map_size;
+
+public: // Basic accessors
+ iterator begin() { return start; }
+ iterator end() { return finish; }
+ const_iterator begin() const { return start; }
+ const_iterator end() const { return finish; }
+
+ reverse_iterator rbegin() { return reverse_iterator(finish); }
+ reverse_iterator rend() { return reverse_iterator(start); }
+ const_reverse_iterator rbegin() const {
+ return const_reverse_iterator(finish);
+ }
+ const_reverse_iterator rend() const {
+ return const_reverse_iterator(start);
+ }
+
+ reference operator[](size_type n) { return start[n]; }
+ const_reference operator[](size_type n) const { return start[n]; }
+
+ reference front() { return *start; }
+ reference back() {
+ iterator tmp = finish;
+ --tmp;
+ return *tmp;
+ }
+ const_reference front() const { return *start; }
+ const_reference back() const {
+ const_iterator tmp = finish;
+ --tmp;
+ return *tmp;
+ }
+
+ size_type size() const { return finish - start;; }
+ size_type max_size() const { return size_type(-1); }
+ bool empty() const { return finish == start; }
+
+public: // Constructor, destructor.
+ deque()
+ : start(), finish(), map(0), map_size(0)
+ {
+ create_map_and_nodes(0);
+ }
+
+ deque(const deque& x)
+ : start(), finish(), map(0), map_size(0)
+ {
+ create_map_and_nodes(x.size());
+# ifdef __STL_USE_EXCEPTIONS
+ try {
+# endif /* __STL_USE_EXCEPTIONS */
+ uninitialized_copy(x.begin(), x.end(), start);
+# ifdef __STL_USE_EXCEPTIONS
+ }
+ catch(...) {
+ destroy_map_and_nodes();
+ throw;
+ }
+# endif /* __STL_USE_EXCEPTIONS */
+ }
+
+ deque(size_type n, const value_type& value)
+ : start(), finish(), map(0), map_size(0) {
+ fill_initialize(n, value);
+ }
+
+ deque(int n, const value_type& value)
+ : start(), finish(), map(0), map_size(0) {
+ fill_initialize(n, value);
+ }
+
+ deque(long n, const value_type& value)
+ : start(), finish(), map(0), map_size(0) {
+ fill_initialize(n, value);
+ }
+
+ explicit deque(size_type n)
+ : start(), finish(), map(0), map_size(0) {
+ fill_initialize(n, value_type());
+ }
+
+#ifdef __STL_MEMBER_TEMPLATES
+
+ template <class InputIterator>
+ deque(InputIterator first, InputIterator last)
+ : start(), finish(), map(0), map_size(0)
+ {
+ range_initialize(first, last, iterator_category(first));
+ }
+
+#else /* __STL_MEMBER_TEMPLATES */
+
+ deque(const value_type* first, const value_type* last)
+ : start(), finish(), map(0), map_size(0)
+ {
+ create_map_and_nodes(last - first);
+# ifdef __STL_USE_EXCEPTIONS
+ try {
+# endif /* __STL_USE_EXCEPTIONS */
+ uninitialized_copy(first, last, start);
+# ifdef __STL_USE_EXCEPTIONS
+ }
+ catch(...) {
+ destroy_map_and_nodes();
+ throw;
+ }
+# endif /* __STL_USE_EXCEPTIONS */
+ }
+
+ deque(const_iterator first, const_iterator last)
+ : start(), finish(), map(0), map_size(0)
+ {
+ create_map_and_nodes(last - first);
+# ifdef __STL_USE_EXCEPTIONS
+ try {
+# endif /* __STL_USE_EXCEPTIONS */
+ uninitialized_copy(first, last, start);
+# ifdef __STL_USE_EXCEPTIONS
+ }
+ catch(...) {
+ destroy_map_and_nodes();
+ throw;
+ }
+# endif /* __STL_USE_EXCEPTIONS */
+ }
+
+#endif /* __STL_MEMBER_TEMPLATES */
+
+ ~deque() {
+ destroy(start, finish);
+ destroy_map_and_nodes();
+ }
+
+ deque& operator= (const deque& x) {
+ const size_type len = size();
+ if (&x != this) {
+ if (len >= x.size())
+ erase(copy(x.begin(), x.end(), start), finish);
+ else {
+ const_iterator mid = x.begin() + len;
+ copy(x.begin(), mid, start);
+ insert(finish, mid, x.end());
+ }
+ }
+ return *this;
+ }
+
+ void swap(deque& x) {
+ ::swap(start, x.start);
+ ::swap(finish, x.finish);
+ ::swap(map, x.map);
+ ::swap(map_size, x.map_size);
+ }
+
+public: // push_* and pop_*
+
+ void push_back(const value_type& t) {
+ if (finish.cur != finish.last - 1) {
+ construct(finish.cur, t);
+ ++finish.cur;
+ }
+ else
+ push_back_aux(t);
+ }
+
+ void push_front(const value_type& t) {
+ if (start.cur != start.first) {
+ construct(start.cur - 1, t);
+ --start.cur;
+ }
+ else
+ push_front_aux(t);
+ }
+
+ void pop_back() {
+ if (finish.cur != finish.first) {
+ --finish.cur;
+ destroy(finish.cur);
+ }
+ else
+ pop_back_aux();
+ }
+
+ void pop_front() {
+ if (start.cur != start.last - 1) {
+ destroy(start.cur);
+ ++start.cur;
+ }
+ else
+ pop_front_aux();
+ }
+
+public: // Insert
+
+ iterator insert(iterator position, const value_type& x) {
+ if (position.cur == start.cur) {
+ push_front(x);
+ return start;
+ }
+ else if (position.cur == finish.cur) {
+ push_back(x);
+ iterator tmp = finish;
+ --tmp;
+ return tmp;
+ }
+ else {
+ return insert_aux(position, x);
+ }
+ }
+
+ iterator insert(iterator position) { return insert(position, value_type()); }
+
+ void insert(iterator pos, size_type n, const value_type& x);
+
+ void insert(iterator pos, int n, const value_type& x) {
+ insert(pos, (size_type) n, x);
+ }
+ void insert(iterator pos, long n, const value_type& x) {
+ insert(pos, (size_type) n, x);
+ }
+
+#ifdef __STL_MEMBER_TEMPLATES
+
+ template <class InputIterator>
+ void insert(iterator pos, InputIterator first, InputIterator last) {
+ insert(pos, first, last, iterator_category(first));
+ }
+
+#else /* __STL_MEMBER_TEMPLATES */
+
+ void insert(iterator pos, const value_type* first, const value_type* last);
+ void insert(iterator pos, const_iterator first, const_iterator last);
+
+#endif /* __STL_MEMBER_TEMPLATES */
+
+ void resize(size_type new_size, const value_type& x) {
+ const size_type len = size();
+ if (new_size < len)
+ erase(start + new_size, finish);
+ else
+ insert(finish, new_size - len, x);
+ }
+
+ void resize(size_type new_size) { resize(new_size, value_type()); }
+
+public: // Erase
+ void erase(iterator pos) {
+ iterator next = pos;
+ ++next;
+ if (pos - start < size() / 2) {
+ copy_backward(start, pos, next);
+ pop_front();
+ }
+ else {
+ copy(next, finish, pos);
+ pop_back();
+ }
+ }
+
+ void erase(iterator first, iterator last);
+ void clear();
+
+protected: // Internal construction/destruction
+
+ void create_map_and_nodes(size_type num_elements);
+ void destroy_map_and_nodes();
+ void fill_initialize(size_type n, const value_type& value);
+
+#ifdef __STL_MEMBER_TEMPLATES
+
+ template <class InputIterator>
+ void range_initialize(InputIterator first, InputIterator last,
+ input_iterator_tag);
+
+ template <class ForwardIterator>
+ void range_initialize(ForwardIterator first, ForwardIterator last,
+ forward_iterator_tag);
+
+ template <class BidirectionalIterator>
+ void range_initialize(BidirectionalIterator first,
+ BidirectionalIterator last,
+ bidirectional_iterator_tag) {
+ range_initialize(first, last, forward_iterator_tag());
+ }
+
+ template <class RandomAccessIterator>
+ void range_initialize(RandomAccessIterator first, RandomAccessIterator last,
+ random_access_iterator_tag) {
+ range_initialize(first, last, forward_iterator_tag());
+ }
+
+#endif /* __STL_MEMBER_TEMPLATES */
+
+protected: // Internal push_* and pop_*
+
+ void push_back_aux(const value_type& t);
+ void push_front_aux(const value_type& t);
+ void pop_back_aux();
+ void pop_front_aux();
+
+protected: // Internal insert functions
+
+#ifdef __STL_MEMBER_TEMPLATES
+
+ template <class InputIterator>
+ void insert(iterator pos, InputIterator first, InputIterator last,
+ input_iterator_tag);
+
+ template <class ForwardIterator>
+ void insert(iterator pos, ForwardIterator first, ForwardIterator last,
+ forward_iterator_tag);
+
+ template <class BidirectionalIterator>
+ void insert(iterator pos,
+ BidirectionalIterator first, BidirectionalIterator last,
+ bidirectional_iterator_tag) {
+ insert(pos, first, last, forward_iterator_tag());
+ }
+
+ template <class RandomAccessIterator>
+ void insert(iterator pos,
+ RandomAccessIterator first, RandomAccessIterator last,
+ random_access_iterator_tag) {
+ insert(pos, first, last, forward_iterator_tag());
+ }
+#endif /* __STL_MEMBER_TEMPLATES */
+
+ iterator insert_aux(iterator pos, const value_type& x);
+ void insert_aux(iterator pos, size_type n, const value_type& x);
+
+#ifdef __STL_MEMBER_TEMPLATES
+
+ template <class ForwardIterator>
+ void insert_aux(iterator pos, ForwardIterator first, ForwardIterator last,
+ size_type n);
+
+#else /* __STL_MEMBER_TEMPLATES */
+
+ void insert_aux(iterator pos,
+ const value_type* first, const value_type* last,
+ size_type n);
+
+ void insert_aux(iterator pos, const_iterator first, const_iterator last,
+ size_type n);
+
+#endif /* __STL_MEMBER_TEMPLATES */
+
+ iterator reserve_elements_at_front(size_type n) {
+ size_type vacancies = start.cur - start.first;
+ if (n > vacancies)
+ new_elements_at_front(n - vacancies);
+ return start - n;
+ }
+
+ iterator reserve_elements_at_back(size_type n) {
+ size_type vacancies = (finish.last - finish.cur) - 1;
+ if (n > vacancies)
+ new_elements_at_back(n - vacancies);
+ return finish + n;
+ }
+
+ void new_elements_at_front(size_type new_elements);
+ void new_elements_at_back(size_type new_elements);
+
+ void destroy_nodes_at_front(iterator before_start);
+ void destroy_nodes_at_back(iterator after_finish);
+
+protected: // Allocation of map and nodes
+
+ // Makes sure the map has space for new nodes. Does not actually
+ // add the nodes. Can invalidate map pointers. (And consequently,
+ // deque iterators.)
+
+ void reserve_map_at_back (size_type nodes_to_add = 1) {
+ if (nodes_to_add + 1 > map_size - (finish.node - map))
+ reallocate_map(nodes_to_add, false);
+ }
+
+ void reserve_map_at_front (size_type nodes_to_add = 1) {
+ if (nodes_to_add > start.node - map)
+ reallocate_map(nodes_to_add, true);
+ }
+
+ void reallocate_map(size_type nodes_to_add, bool add_at_front);
+
+ pointer allocate_node() { return data_allocator::allocate(buffer_size()); }
+ void deallocate_node(pointer n) {
+ data_allocator::deallocate(n, buffer_size());
+ }
+
+#ifdef __STL_NON_TYPE_TMPL_PARAM_BUG
+public:
+ bool operator==(const deque<T, Alloc, 0>& x) const {
+ return size() == x.size() && equal(begin(), end(), x.begin());
+ }
+ bool operator!=(const deque<T, Alloc, 0>& x) const {
+ return size() != x.size() || !equal(begin(), end(), x.begin());
+ }
+ bool operator<(const deque<T, Alloc, 0>& x) const {
+ return lexicographical_compare(begin(), end(), x.begin(), x.end());
+ }
+#endif /* __STL_NON_TYPE_TMPL_PARAM_BUG */
+};
+
+// Non-inline member functions
+
+template <class T, class Alloc, size_t BufSize>
+void deque<T, Alloc, BufSize>::insert(iterator pos,
+ size_type n, const value_type& x) {
+ if (pos.cur == start.cur) {
+ iterator new_start = reserve_elements_at_front(n);
+ uninitialized_fill(new_start, start, x);
+ start = new_start;
+ }
+ else if (pos.cur == finish.cur) {
+ iterator new_finish = reserve_elements_at_back(n);
+ uninitialized_fill(finish, new_finish, x);
+ finish = new_finish;
+ }
+ else
+ insert_aux(pos, n, x);
+}
+
+#ifndef __STL_MEMBER_TEMPLATES
+
+template <class T, class Alloc, size_t BufSize>
+void deque<T, Alloc, BufSize>::insert(iterator pos,
+ const value_type* first,
+ const value_type* last) {
+ size_type n = last - first;
+ if (pos.cur == start.cur) {
+ iterator new_start = reserve_elements_at_front(n);
+# ifdef __STL_USE_EXCEPTIONS
+ try {
+# endif
+ uninitialized_copy(first, last, new_start);
+ start = new_start;
+# ifdef __STL_USE_EXCEPTIONS
+ }
+ catch(...) {
+ destroy_nodes_at_front(new_start);
+ throw;
+ }
+# endif
+ }
+ else if (pos.cur == finish.cur) {
+ iterator new_finish = reserve_elements_at_back(n);
+# ifdef __STL_USE_EXCEPTIONS
+ try {
+# endif
+ uninitialized_copy(first, last, finish);
+ finish = new_finish;
+# ifdef __STL_USE_EXCEPTIONS
+ }
+ catch(...) {
+ destroy_nodes_at_back(new_finish);
+ throw;
+ }
+# endif
+ }
+ else
+ insert_aux(pos, first, last, n);
+}
+
+template <class T, class Alloc, size_t BufSize>
+void deque<T, Alloc, BufSize>::insert(iterator pos,
+ const_iterator first,
+ const_iterator last)
+{
+ size_type n = last - first;
+ if (pos.cur == start.cur) {
+ iterator new_start = reserve_elements_at_front(n);
+# ifdef __STL_USE_EXCEPTIONS
+ try {
+# endif
+ uninitialized_copy(first, last, new_start);
+ start = new_start;
+# ifdef __STL_USE_EXCEPTIONS
+ }
+ catch(...) {
+ destroy_nodes_at_front(new_start);
+ throw;
+ }
+# endif
+ }
+ else if (pos.cur == finish.cur) {
+ iterator new_finish = reserve_elements_at_back(n);
+# ifdef __STL_USE_EXCEPTIONS
+ try {
+# endif
+ uninitialized_copy(first, last, finish);
+ finish = new_finish;
+# ifdef __STL_USE_EXCEPTIONS
+ }
+ catch(...) {
+ destroy_nodes_at_back(new_finish);
+ throw;
+ }
+# endif
+ }
+ else
+ insert_aux(pos, first, last, n);
+}
+
+#endif /* __STL_MEMBER_TEMPLATES */
+
+template <class T, class Alloc, size_t BufSize>
+void deque<T, Alloc, BufSize>::erase(iterator first, iterator last) {
+ if (first == start && last == finish)
+ clear();
+ else {
+ difference_type n = last - first;
+ difference_type elems_before = first - start;
+ if (elems_before < (size() - n) / 2) {
+ copy_backward(start, first, last);
+ iterator new_start = start + n;
+ destroy(start, new_start);
+ for (map_pointer cur = start.node; cur < new_start.node; ++cur)
+ data_allocator::deallocate(*cur, buffer_size());
+ start = new_start;
+ }
+ else {
+ copy(last, finish, first);
+ iterator new_finish = finish - n;
+ destroy(new_finish, finish);
+ for (map_pointer cur = new_finish.node + 1; cur <= finish.node; ++cur)
+ data_allocator::deallocate(*cur, buffer_size());
+ finish = new_finish;
+ }
+ }
+}
+
+template <class T, class Alloc, size_t BufSize>
+void deque<T, Alloc, BufSize>::clear() {
+ for (map_pointer node = start.node + 1; node < finish.node; ++node) {
+ destroy(*node, *node + buffer_size());
+ data_allocator::deallocate(*node, buffer_size());
+ }
+
+ if (start.node != finish.node) {
+ destroy(start.cur, start.last);
+ destroy(finish.first, finish.cur);
+ data_allocator::deallocate(finish.first, buffer_size());
+ }
+ else
+ destroy(start.cur, finish.cur);
+
+ finish = start;
+}
+
+template <class T, class Alloc, size_t BufSize>
+void deque<T, Alloc, BufSize>::create_map_and_nodes(size_type num_elements) {
+ size_type num_nodes = num_elements / buffer_size() + 1;
+
+ map_size = max(initial_map_size(), num_nodes + 2);
+ map = map_allocator::allocate(map_size);
+
+ map_pointer nstart = map + (map_size - num_nodes) / 2;
+ map_pointer nfinish = nstart + num_nodes - 1;
+
+ map_pointer cur;
+# ifdef __STL_USE_EXCEPTIONS
+ try {
+# endif /* __STL_USE_EXCEPTIONS */
+ for (cur = nstart; cur <= nfinish; ++cur)
+ *cur = allocate_node();
+# ifdef __STL_USE_EXCEPTIONS
+ }
+ catch(...) {
+ for (map_pointer n = nstart; n < cur; ++n)
+ deallocate_node(*n);
+ map_allocator::deallocate(map, map_size);
+ throw;
+ }
+# endif /* __STL_USE_EXCEPTIONS */
+
+ start.set_node(nstart);
+ finish.set_node(nfinish);
+ start.cur = start.first;
+ finish.cur = finish.first + num_elements % buffer_size();
+}
+
+// This is only used as a cleanup function in catch clauses.
+template <class T, class Alloc, size_t BufSize>
+void deque<T, Alloc, BufSize>::destroy_map_and_nodes() {
+ for (map_pointer cur = start.node; cur <= finish.node; ++cur)
+ deallocate_node(*cur);
+ map_allocator::deallocate(map, map_size);
+}
+
+
+template <class T, class Alloc, size_t BufSize>
+void deque<T, Alloc, BufSize>::fill_initialize(size_type n,
+ const value_type& value) {
+ create_map_and_nodes(n);
+ map_pointer cur;
+# ifdef __STL_USE_EXCEPTIONS
+ try {
+# endif /* __STL_USE_EXCEPTIONS */
+ for (cur = start.node; cur < finish.node; ++cur)
+ uninitialized_fill(*cur, *cur + buffer_size(), value);
+ uninitialized_fill(finish.first, finish.cur, value);
+# ifdef __STL_USE_EXCEPTIONS
+ }
+ catch(...) {
+ for (map_pointer n = start.node; n < cur; ++n)
+ destroy(*cur, *cur + buffer_size());
+ destroy_map_and_nodes();
+ throw;
+ }
+# endif /* __STL_USE_EXCEPTIONS */
+}
+
+#ifdef __STL_MEMBER_TEMPLATES
+
+template <class T, class Alloc, size_t BufSize>
+template <class InputIterator>
+void deque<T, Alloc, BufSize>::range_initialize(InputIterator first,
+ InputIterator last,
+ input_iterator_tag) {
+ create_map_and_nodes(0);
+ for ( ; first != last; ++first)
+ push_back(*first);
+}
+
+template <class T, class Alloc, size_t BufSize>
+template <class ForwardIterator>
+void deque<T, Alloc, BufSize>::range_initialize(ForwardIterator first,
+ ForwardIterator last,
+ forward_iterator_tag) {
+ size_type n = 0;
+ distance(first, last, n);
+ create_map_and_nodes(n);
+# ifdef __STL_USE_EXCEPTIONS
+ try {
+# endif /* __STL_USE_EXCEPTIONS */
+ uninitialized_copy(first, last, start);
+# ifdef __STL_USE_EXCEPTIONS
+ }
+ catch(...) {
+ destroy_map_and_nodes();
+ throw;
+ }
+# endif /* __STL_USE_EXCEPTIONS */
+}
+
+#endif /* __STL_MEMBER_TEMPLATES */
+
+// Called only if finish.cur == finish.last - 1.
+template <class T, class Alloc, size_t BufSize>
+void deque<T, Alloc, BufSize>::push_back_aux(const value_type& t) {
+ value_type t_copy = t;
+ reserve_map_at_back();
+ *(finish.node + 1) = allocate_node();
+# ifdef __STL_USE_EXCEPTIONS
+ try {
+# endif /* __STL_USE_EXCEPTIONS */
+ construct(finish.cur, t_copy);
+ finish.set_node(finish.node + 1);
+ finish.cur = finish.first;
+# ifdef __STL_USE_EXCEPTIONS
+ }
+ catch(...) {
+ deallocate_node(*(finish.node + 1));
+ throw;
+ }
+# endif /* __STL_USE_EXCEPTIONS */
+}
+
+// Called only if start.cur == start.first.
+template <class T, class Alloc, size_t BufSize>
+void deque<T, Alloc, BufSize>::push_front_aux(const value_type& t) {
+ value_type t_copy = t;
+ reserve_map_at_front();
+ *(start.node - 1) = allocate_node();
+# ifdef __STL_USE_EXCEPTIONS
+ try {
+# endif /* __STL_USE_EXCEPTIONS */
+ start.set_node(start.node - 1);
+ start.cur = start.last - 1;
+ construct(start.cur, t_copy);
+# ifdef __STL_USE_EXCEPTIONS
+ }
+ catch(...) {
+ start.set_node(start.node + 1);
+ start.cur = start.first;
+ deallocate_node(*(start.node - 1));
+ throw;
+ }
+# endif /* __STL_USE_EXCEPTIONS */
+}
+
+// Called only if finish.cur == finish.first.
+template <class T, class Alloc, size_t BufSize>
+void deque<T, Alloc, BufSize>:: pop_back_aux() {
+ deallocate_node(finish.first);
+ finish.set_node(finish.node - 1);
+ finish.cur = finish.last - 1;
+ destroy(finish.cur);
+}
+
+// Called only if start.cur == start.last - 1. Note that if the deque
+// has at least one element (a necessary precondition for this member
+// function), and if start.cur == start.last, then the deque must have
+// at least two nodes.
+template <class T, class Alloc, size_t BufSize>
+void deque<T, Alloc, BufSize>::pop_front_aux() {
+ destroy(start.cur);
+ deallocate_node(start.first);
+ start.set_node(start.node + 1);
+ start.cur = start.first;
+}
+
+#ifdef __STL_MEMBER_TEMPLATES
+
+template <class T, class Alloc, size_t BufSize>
+template <class InputIterator>
+void deque<T, Alloc, BufSize>::insert(iterator pos,
+ InputIterator first, InputIterator last,
+ input_iterator_tag) {
+ copy(first, last, inserter(*this, pos));
+}
+
+template <class T, class Alloc, size_t BufSize>
+template <class ForwardIterator>
+void deque<T, Alloc, BufSize>::insert(iterator pos,
+ ForwardIterator first,
+ ForwardIterator last,
+ forward_iterator_tag) {
+ size_type n = 0;
+ distance(first, last, n);
+ if (pos.cur == start.cur) {
+ iterator new_start = reserve_elements_at_front(n);
+# ifdef __STL_USE_EXCEPTIONS
+ try {
+# endif
+ uninitialized_copy(first, last, new_start);
+ start = new_start;
+# ifdef __STL_USE_EXCEPTIONS
+ }
+ catch(...) {
+ destroy_nodes_at_front(new_start);
+ throw;
+ }
+# endif
+ }
+ else if (pos.cur == finish.cur) {
+ iterator new_finish = reserve_elements_at_back(n);
+# ifdef __STL_USE_EXCEPTIONS
+ try {
+# endif
+ uninitialized_copy(first, last, finish);
+ finish = new_finish;
+# ifdef __STL_USE_EXCEPTIONS
+ }
+ catch(...) {
+ destroy_nodes_at_back(new_finish);
+ throw;
+ }
+# endif
+ }
+ else
+ insert_aux(pos, first, last, n);
+}
+
+#endif /* __STL_MEMBER_TEMPLATES */
+
+template <class T, class Alloc, size_t BufSize>
+deque<T, Alloc, BufSize>::iterator
+deque<T, Alloc, BufSize>::insert_aux(iterator pos, const value_type& x) {
+ difference_type index = pos - start;
+ value_type x_copy = x;
+ if (index < size() / 2) {
+ push_front(front());
+ iterator front1 = start;
+ ++front1;
+ iterator front2 = front1;
+ ++front2;
+ pos = start + index;
+ iterator pos1 = pos;
+ ++pos1;
+ copy(front2, pos1, front1);
+ }
+ else {
+ push_back(back());
+ iterator back1 = finish;
+ --back1;
+ iterator back2 = back1;
+ --back2;
+ pos = start + index;
+ copy_backward(pos, back2, back1);
+ }
+ *pos = x_copy;
+ return pos;
+}
+
+template <class T, class Alloc, size_t BufSize>
+void deque<T, Alloc, BufSize>::insert_aux(iterator pos,
+ size_type n, const value_type& x) {
+ const difference_type elems_before = pos - start;
+ size_type length = size();
+ value_type x_copy = x;
+ if (elems_before < length / 2) {
+ iterator new_start = reserve_elements_at_front(n);
+ iterator old_start = start;
+ pos = start + elems_before;
+# ifdef __STL_USE_EXCEPTIONS
+ try {
+# endif /* __STL_USE_EXCEPTIONS */
+ if (elems_before >= n) {
+ iterator start_n = start + n;
+ uninitialized_copy(start, start_n, new_start);
+ start = new_start;
+ copy(start_n, pos, old_start);
+ fill(pos - n, pos, x_copy);
+ }
+ else {
+ __uninitialized_copy_fill(start, pos, new_start, start, x_copy);
+ start = new_start;
+ fill(old_start, pos, x_copy);
+ }
+# ifdef __STL_USE_EXCEPTIONS
+ }
+ catch(...) {
+ destroy_nodes_at_front(new_start);
+ throw;
+ }
+# endif /* __STL_USE_EXCEPTIONS */
+ }
+ else {
+ iterator new_finish = reserve_elements_at_back(n);
+ iterator old_finish = finish;
+ const difference_type elems_after = length - elems_before;
+ pos = finish - elems_after;
+# ifdef __STL_USE_EXCEPTIONS
+ try {
+# endif /* __STL_USE_EXCEPTIONS */
+ if (elems_after > n) {
+ iterator finish_n = finish - n;
+ uninitialized_copy(finish_n, finish, finish);
+ finish = new_finish;
+ copy_backward(pos, finish_n, old_finish);
+ fill(pos, pos + n, x_copy);
+ }
+ else {
+ __uninitialized_fill_copy(finish, pos + n, x_copy, pos, finish);
+ finish = new_finish;
+ fill(pos, old_finish, x_copy);
+ }
+# ifdef __STL_USE_EXCEPTIONS
+ }
+ catch(...) {
+ destroy_nodes_at_back(new_finish);
+ throw;
+ }
+# endif /* __STL_USE_EXCEPTIONS */
+ }
+}
+
+#ifdef __STL_MEMBER_TEMPLATES
+
+template <class T, class Alloc, size_t BufSize>
+template <class ForwardIterator>
+void deque<T, Alloc, BufSize>::insert_aux(iterator pos,
+ ForwardIterator first,
+ ForwardIterator last,
+ size_type n)
+{
+ const difference_type elems_before = pos - start;
+ size_type length = size();
+ if (elems_before < length / 2) {
+ iterator new_start = reserve_elements_at_front(n);
+ iterator old_start = start;
+ pos = start + elems_before;
+# ifdef __STL_USE_EXCEPTIONS
+ try {
+# endif /* __STL_USE_EXCEPTIONS */
+ if (elems_before >= n) {
+ iterator start_n = start + n;
+ uninitialized_copy(start, start_n, new_start);
+ start = new_start;
+ copy(start_n, pos, old_start);
+ copy(first, last, pos - n);
+ }
+ else {
+ ForwardIterator mid = first;
+ advance(mid, n - elems_before);
+ __uninitialized_copy_copy(start, pos, first, mid, new_start);
+ start = new_start;
+ copy(mid, last, old_start);
+ }
+# ifdef __STL_USE_EXCEPTIONS
+ }
+ catch(...) {
+ destroy_nodes_at_front(new_start);
+ throw;
+ }
+# endif /* __STL_USE_EXCEPTIONS */
+ }
+ else {
+ iterator new_finish = reserve_elements_at_back(n);
+ iterator old_finish = finish;
+ const difference_type elems_after = length - elems_before;
+ pos = finish - elems_after;
+# ifdef __STL_USE_EXCEPTIONS
+ try {
+# endif /* __STL_USE_EXCEPTIONS */
+ if (elems_after > n) {
+ iterator finish_n = finish - n;
+ uninitialized_copy(finish_n, finish, finish);
+ finish = new_finish;
+ copy_backward(pos, finish_n, old_finish);
+ copy(first, last, pos);
+ }
+ else {
+ ForwardIterator mid = first;
+ advance(mid, elems_after);
+ __uninitialized_copy_copy(mid, last, pos, finish, finish);
+ finish = new_finish;
+ copy(first, mid, pos);
+ }
+# ifdef __STL_USE_EXCEPTIONS
+ }
+ catch(...) {
+ destroy_nodes_at_back(new_finish);
+ throw;
+ }
+# endif /* __STL_USE_EXCEPTIONS */
+ }
+}
+
+#else /* __STL_MEMBER_TEMPLATES */
+
+template <class T, class Alloc, size_t BufSize>
+void deque<T, Alloc, BufSize>::insert_aux(iterator pos,
+ const value_type* first,
+ const value_type* last,
+ size_type n)
+{
+ const difference_type elems_before = pos - start;
+ size_type length = size();
+ if (elems_before < length / 2) {
+ iterator new_start = reserve_elements_at_front(n);
+ iterator old_start = start;
+ pos = start + elems_before;
+# ifdef __STL_USE_EXCEPTIONS
+ try {
+# endif /* __STL_USE_EXCEPTIONS */
+ if (elems_before >= n) {
+ iterator start_n = start + n;
+ uninitialized_copy(start, start_n, new_start);
+ start = new_start;
+ copy(start_n, pos, old_start);
+ copy(first, last, pos - n);
+ }
+ else {
+ const value_type* mid = first + (n - elems_before);
+ __uninitialized_copy_copy(start, pos, first, mid, new_start);
+ start = new_start;
+ copy(mid, last, old_start);
+ }
+# ifdef __STL_USE_EXCEPTIONS
+ }
+ catch(...) {
+ destroy_nodes_at_front(new_start);
+ throw;
+ }
+# endif /* __STL_USE_EXCEPTIONS */
+ }
+ else {
+ iterator new_finish = reserve_elements_at_back(n);
+ iterator old_finish = finish;
+ const difference_type elems_after = length - elems_before;
+ pos = finish - elems_after;
+# ifdef __STL_USE_EXCEPTIONS
+ try {
+# endif /* __STL_USE_EXCEPTIONS */
+ if (elems_after > n) {
+ iterator finish_n = finish - n;
+ uninitialized_copy(finish_n, finish, finish);
+ finish = new_finish;
+ copy_backward(pos, finish_n, old_finish);
+ copy(first, last, pos);
+ }
+ else {
+ const value_type* mid = first + elems_after;
+ __uninitialized_copy_copy(mid, last, pos, finish, finish);
+ finish = new_finish;
+ copy(first, mid, pos);
+ }
+# ifdef __STL_USE_EXCEPTIONS
+ }
+ catch(...) {
+ destroy_nodes_at_back(new_finish);
+ throw;
+ }
+# endif /* __STL_USE_EXCEPTIONS */
+ }
+}
+
+template <class T, class Alloc, size_t BufSize>
+void deque<T, Alloc, BufSize>::insert_aux(iterator pos,
+ const_iterator first,
+ const_iterator last,
+ size_type n)
+{
+ const difference_type elems_before = pos - start;
+ size_type length = size();
+ if (elems_before < length / 2) {
+ iterator new_start = reserve_elements_at_front(n);
+ iterator old_start = start;
+ pos = start + elems_before;
+# ifdef __STL_USE_EXCEPTIONS
+ try {
+# endif /* __STL_USE_EXCEPTIONS */
+ if (elems_before >= n) {
+ iterator start_n = start + n;
+ uninitialized_copy(start, start_n, new_start);
+ start = new_start;
+ copy(start_n, pos, old_start);
+ copy(first, last, pos - n);
+ }
+ else {
+ const_iterator mid = first + (n - elems_before);
+ __uninitialized_copy_copy(start, pos, first, mid, new_start);
+ start = new_start;
+ copy(mid, last, old_start);
+ }
+# ifdef __STL_USE_EXCEPTIONS
+ }
+ catch(...) {
+ destroy_nodes_at_front(new_start);
+ throw;
+ }
+# endif /* __STL_USE_EXCEPTIONS */
+ }
+ else {
+ iterator new_finish = reserve_elements_at_back(n);
+ iterator old_finish = finish;
+ const difference_type elems_after = length - elems_before;
+ pos = finish - elems_after;
+# ifdef __STL_USE_EXCEPTIONS
+ try {
+# endif /* __STL_USE_EXCEPTIONS */
+ if (elems_after > n) {
+ iterator finish_n = finish - n;
+ uninitialized_copy(finish_n, finish, finish);
+ finish = new_finish;
+ copy_backward(pos, finish_n, old_finish);
+ copy(first, last, pos);
+ }
+ else {
+ const_iterator mid = first + elems_after;
+ __uninitialized_copy_copy(mid, last, pos, finish, finish);
+ finish = new_finish;
+ copy(first, mid, pos);
+ }
+# ifdef __STL_USE_EXCEPTIONS
+ }
+ catch(...) {
+ destroy_nodes_at_back(new_finish);
+ throw;
+ }
+# endif /* __STL_USE_EXCEPTIONS */
+ }
+}
+
+#endif /* __STL_MEMBER_TEMPLATES */
+
+template <class T, class Alloc, size_t BufSize>
+void deque<T, Alloc, BufSize>::new_elements_at_front(size_type new_elements) {
+ size_type new_nodes = (new_elements + buffer_size() - 1) / buffer_size();
+ reserve_map_at_front(new_nodes);
+ size_type i;
+# ifdef __STL_USE_EXCEPTIONS
+ try {
+# endif /* __STL_USE_EXCEPTIONS */
+ for (i = 1; i <= new_nodes; ++i)
+ *(start.node - i) = allocate_node();
+# ifdef __STL_USE_EXCEPTIONS
+ }
+ catch(...) {
+ for (size_type j = 1; j < i; ++j)
+ deallocate_node(*(start.node - j));
+ throw;
+ }
+# endif /* __STL_USE_EXCEPTIONS */
+}
+
+template <class T, class Alloc, size_t BufSize>
+void deque<T, Alloc, BufSize>::new_elements_at_back(size_type new_elements) {
+ size_type new_nodes = (new_elements + buffer_size() - 1) / buffer_size();
+ reserve_map_at_back(new_nodes);
+ size_type i;
+# ifdef __STL_USE_EXCEPTIONS
+ try {
+# endif /* __STL_USE_EXCEPTIONS */
+ for (i = 1; i <= new_nodes; ++i)
+ *(finish.node + i) = allocate_node();
+# ifdef __STL_USE_EXCEPTIONS
+ }
+ catch(...) {
+ for (size_type j = 1; j < i; ++j)
+ deallocate_node(*(finish.node + j));
+ throw;
+ }
+# endif /* __STL_USE_EXCEPTIONS */
+}
+
+template <class T, class Alloc, size_t BufSize>
+void deque<T, Alloc, BufSize>::destroy_nodes_at_front(iterator before_start) {
+ for (map_pointer n = before_start.node; n < start.node; ++n)
+ deallocate_node(*n);
+}
+
+template <class T, class Alloc, size_t BufSize>
+void deque<T, Alloc, BufSize>::destroy_nodes_at_back(iterator after_finish) {
+ for (map_pointer n = after_finish.node; n > finish.node; --n)
+ deallocate_node(*n);
+}
+
+template <class T, class Alloc, size_t BufSize>
+void deque<T, Alloc, BufSize>::reallocate_map(size_type nodes_to_add,
+ bool add_at_front) {
+ size_type old_num_nodes = finish.node - start.node + 1;
+ size_type new_num_nodes = old_num_nodes + nodes_to_add;
+
+ map_pointer new_nstart;
+ if (map_size > 2 * new_num_nodes) {
+ new_nstart = map + (map_size - new_num_nodes) / 2
+ + (add_at_front ? nodes_to_add : 0);
+ if (new_nstart < start.node)
+ copy(start.node, finish.node + 1, new_nstart);
+ else
+ copy_backward(start.node, finish.node + 1, new_nstart + old_num_nodes);
+ }
+ else {
+ size_type new_map_size = map_size + max(map_size, nodes_to_add) + 2;
+
+ map_pointer new_map = map_allocator::allocate(new_map_size);
+ new_nstart = new_map + (new_map_size - new_num_nodes) / 2
+ + (add_at_front ? nodes_to_add : 0);
+ copy(start.node, finish.node + 1, new_nstart);
+ map_allocator::deallocate(map, map_size);
+
+ map = new_map;
+ map_size = new_map_size;
+ }
+
+ start.set_node(new_nstart);
+ finish.set_node(new_nstart + old_num_nodes - 1);
+}
+
+
+// Nonmember functions.
+
+#ifndef __STL_NON_TYPE_TMPL_PARAM_BUG
+
+template <class T, class Alloc, size_t BufSiz>
+bool operator==(const deque<T, Alloc, BufSiz>& x,
+ const deque<T, Alloc, BufSiz>& y) {
+ return x.size() == y.size() && equal(x.begin(), x.end(), y.begin());
+}
+
+template <class T, class Alloc, size_t BufSiz>
+bool operator<(const deque<T, Alloc, BufSiz>& x,
+ const deque<T, Alloc, BufSiz>& y) {
+ return lexicographical_compare(x.begin(), x.end(), y.begin(), y.end());
+}
+
+#endif /* __STL_NON_TYPE_TMPL_PARAM_BUG */
+
+
+#endif /* __SGI_STL_DEQUE_H */
+