/** -*- C++ -*- ** ** KAI C++ Compiler ** ** Copyright (C) 1996-2001 Intel Corp. All rights reserved. **/ /** ** Lib++ : The Modena C++ Standard Library, ** Version 2.4, October 1997 ** ** Copyright (c) 1995-1997 Modena Software Inc. **/ #ifndef __KAI_DEQUE #define __KAI_DEQUE #include #include #include #include #include #include #undef Allocator /* Old STL codes define Allocator */ namespace std { template > class deque { public: // types: typedef typename Allocator::reference reference; typedef typename Allocator::const_reference const_reference; class iterator; class const_iterator; typedef typename Allocator::size_type size_type; typedef typename Allocator::difference_type difference_type; typedef T value_type; typedef Allocator allocator_type; typedef typename Allocator::pointer pointer; typedef typename Allocator::const_pointer const_pointer; typedef std::reverse_iterator reverse_iterator; typedef std::reverse_iterator const_reverse_iterator; friend class iterator; friend class const_iterator; private: typedef typename Allocator:: template rebind::other map_allocator_type; typedef typename map_allocator_type::pointer map_pointer; static const int __sz1 = sizeof(T)>4096 ? 1 : 4096 / sizeof(T); static const size_type BUF_SIZE = (__sz1 < 20) ? __sz1 : 20; void allocate_at_begin(); void allocate_at_end(); void deallocate_at_begin(); void deallocate_at_end(); // Added by KAI to perform the magic required by the C++ Standard 23.1.1 para 9. template class _Helper { }; template void _initialize(Iterator first, Iterator last, _Helper *) { size_type n = (size_type)first; const T value = (T) last; insert(begin(), n, value); } template void _initialize(Iterator first, Iterator last, _Helper *) { difference_type i = 0; MSIPL_TRY { for (; first != last; ++first, ++i) push_back(*first); } MSIPL_CATCH { for (difference_type j = i; j > 0; --j) pop_back(); MSIPL_RETHROW; } } template void _insert(iterator position, InputIterator first, InputIterator last, _Helper *) { size_type n = static_cast(first); const T value = static_cast(last); insert(position, n, value); } template void _insert(iterator position, InputIterator first, InputIterator last, _Helper *) { // KAI change to make simple input_iterators(i.e. istream_iterator) work. _insert_iterator(position, first, last, (iterator_traits::iterator_category *)0); } template void _insert_iterator(iterator position, InputIterator first, InputIterator last, input_iterator_tag *) { // We cannot compute the distance without distructivly stepping through the iterator. // So we create a new deque of the values and then insert that range(which we can compute the size) deque tmp(first,last); insert(position, tmp.begin(), tmp.end()); } template void _insert_iterator(iterator position, InputIterator first, InputIterator last, random_access_iterator_tag *); struct cleanup; friend struct cleanup; struct cleanup { deque *my_deque; size_t n; bool from_head; cleanup(deque *d, bool fh, size_t cnt = 0) : my_deque(d), from_head(fh), n(cnt) { } ~cleanup() { while (n--) { from_head? my_deque->pop_front() : my_deque->pop_back(); } } void incr() { n++; } void clear() {n=0;} }; public: // 23.2.1.1 construct/copy/destroy explicit deque() : start(this), finish(this), length(0), map(0), map_size(0) {} explicit deque(const Allocator& a) : start(this), finish(this), length(0), map(0), map_size(0), alloc(a) {} explicit deque(size_type n) : start(this), finish(this), length(0), map(0), map_size(0) { insert(begin(), n, T()); } explicit deque(size_type n, const T& value) : start(this), finish(this), length(0), map(0), map_size(0) { insert(begin(), n, value); } explicit deque(size_type n, const T& value, const Allocator& a) : start(this), finish(this), length(0), map(0), map_size(0), alloc(a) { insert(begin(), n, value); } template __noinline deque(Iterator first, Iterator last) : start(this), finish(this), length(0), map(0), map_size(0) { _initialize(first, last, (_Helper::is_integer> *)0); } template __noinline deque(Iterator first, Iterator last, const Allocator& a) : start(this), finish(this), length(0), map(0), map_size(0), alloc(a) { _initialize(first, last, (_Helper::is_integer> *)0); } deque(const deque& x); ~deque(); deque& operator=(const deque& x); template void assign(InputIterator first, InputIterator last) { erase(begin(), end()); insert(begin(), first, last); } void assign(size_type n, const T& t) { erase(begin(), end()); insert(begin(), n, t); } inline allocator_type get_allocator() const { return alloc; } // iterators: iterator begin() { return start; } const_iterator begin() const { return start; } iterator end() { return finish; } const_iterator end() const { return finish; } reverse_iterator rbegin() { return reverse_iterator(end()); } const_reverse_iterator rbegin() const { return const_reverse_iterator(end()); } reverse_iterator rend() { return reverse_iterator(begin()); } const_reverse_iterator rend() const { return const_reverse_iterator(begin()); } // 23.2.1.2 capacity: size_type size() const { return length; } size_type max_size() const { return alloc.max_size(); } void resize(size_type new_size) { resize(new_size, T()); } void resize(size_type new_size, T c) { if (new_size > length) insert(end(), new_size - length, c); else if (new_size < length) erase(begin() + new_size, end()); } bool empty() const { return length == 0; } // element access: reference operator[](size_type n) { return *(begin() + n); } const_reference operator[](size_type n) const { return *(begin() + n); } reference at(size_type n) { if (n>=length) out_of_range::__throw("Out of range exception occurred"); return *(begin() + n); } const_reference at(size_type n) const { if (n>=length) out_of_range::__throw("Out of range exception occurred"); return *(begin() + n); } reference front() { return *start; } const_reference front() const { return *start; } reference back() { iterator tmp = finish; --tmp; return *tmp; } const_reference back() const { iterator tmp = finish; --tmp; return *tmp; } // 23.2.1.3 modifiers: void push_front(const T& x); void push_back(const T& x); iterator insert(iterator position, const T& x); void insert(iterator position, size_type n, const T& x); template __noinline void insert(iterator position, InputIterator first, InputIterator last) { _insert(position, first, last, (_Helper::is_integer> *)0); } void pop_front(); void pop_back(); iterator erase(iterator position); iterator erase(iterator first, iterator last); void swap(deque& x) { std::swap(start, x.start); std::swap(finish, x.finish); std::swap(map, x.map); std::swap(length, x.length); std::swap(map_size, x.map_size); std::swap(alloc, x.alloc); } void clear() { erase(begin(), end()); } // iterator class iterator : public std::iterator { friend class deque; friend class deque::const_iterator; friend iterator operator+(const difference_type n, const iterator& iter) { deque::iterator tmp = iter; return tmp += n; } protected: pointer current; pointer first; pointer last; map_pointer node; iterator(pointer x, map_pointer y, deque* dq) : current(x), first(*y), last(*y + BUF_SIZE), node(y) {} iterator(deque *dq) : current(0), first(0), last(0), node(0) {} public: iterator() : current(0), first(0), last(0), node(0) { } reference operator*() const { return *current; } pointer operator->() const { return &(operator*()); } iterator& operator++() { if (++current == last){ first = *(++node); current = first; last = first + BUF_SIZE; } return *this; } iterator operator++(int) { iterator tmp = *this; ++*this; return tmp; } iterator& operator--() { if (current == first) { first = *(--node); last = first + BUF_SIZE; current = last; } --current; return *this; } iterator operator--(int) { iterator tmp = *this; --*this; return tmp; } __noinline iterator& operator+=(const difference_type n) { difference_type offset = n + (current - first); difference_type num_node_to_jump = offset >= 0 ? offset / BUF_SIZE : -((-offset + BUF_SIZE - 1) / BUF_SIZE); if (num_node_to_jump == 0) current += n; else { node = node + num_node_to_jump; first = *node; last = first + BUF_SIZE; current = first + (offset - num_node_to_jump * BUF_SIZE); } return *this; } iterator& operator-=(const difference_type n) { return *this += -n; } iterator operator+(const difference_type n) const { iterator tmp = *this; return tmp += n; } iterator operator-(const difference_type n) const { iterator tmp = *this; return tmp -= n; } reference operator[](const difference_type n) const { return *(*this + n); } difference_type operator-(const iterator& x) const { return node == x.node ? current - x.current : BUF_SIZE *(node - x.node - 1) + (current - first)+ (x.last - x.current); } difference_type operator-(const const_iterator& x) const { return node == x.node ? current - x.current : BUF_SIZE *(node - x.node - 1) + (current - first)+ (x.last - x.current); } bool operator==(const iterator& x) const { return current == x.current; } bool operator==(const const_iterator& x) const { return current == x.current; } bool operator<(const iterator& x) const { return(node == x.node) ? (current < x.current) : (node < x.node); } bool operator<(const const_iterator& x) const { return(node == x.node) ? (current < x.current) : (node < x.node); } bool operator!=(const iterator& y) const { return ! (*this == y); } bool operator>(const iterator& y) const { return y < *this; } bool operator<=(const iterator& y) const { return ! (y < *this); } bool operator>=(const iterator& y) const { return ! (*this < y); } bool operator!=(const const_iterator& y) const { return ! (*this == y); } bool operator>(const const_iterator& y) const { return y < *this; } bool operator<=(const const_iterator& y) const { return ! (y < *this); } bool operator>=(const const_iterator& y) const { return(y < *this); } }; // const_iterator class const_iterator : public std::iterator { friend class deque; friend class deque::iterator; friend const_iterator operator+(const difference_type n, const const_iterator& iter) { deque::const_iterator tmp = iter; return tmp += n; } protected: const_pointer current; const_pointer first; const_pointer last; map_pointer node; const_iterator(pointer x, map_pointer y, deque* dq) : current(x), first(*y), last(*y + BUF_SIZE), node(y) {} public: const_iterator() : current(0), first(0), last(0), node(0) {} const_iterator(const deque::iterator& x) : current(x.current), first(x.first), last(x.last), node(x.node) {} const_reference operator*() const { return *current; } const_pointer operator->() const { return &(operator*()); } const_iterator& operator++() { if (++current == last) { first = *(++node); current = first; last = first + BUF_SIZE; } return *this; } const_iterator operator++(int) { const_iterator tmp = *this; ++*this; return tmp; } const_iterator& operator--() { if (current == first) { first = *(--node); last = first + BUF_SIZE; current = last; } --current; return *this; } const_iterator operator--(int) { const_iterator tmp = *this; --*this; return tmp; } __noinline const_iterator& operator+=(const difference_type n) { difference_type offset = n + (current - first); difference_type num_node_to_jump = offset >= 0 ? offset / BUF_SIZE : -((-offset + BUF_SIZE - 1) / BUF_SIZE); if (num_node_to_jump == 0) current += n; else { node = node + num_node_to_jump; first = *node; last = first + BUF_SIZE; current = first + (offset - num_node_to_jump * BUF_SIZE); } return *this; } const_iterator& operator-=(const difference_type n) { return *this += -n; } const_iterator operator+(const difference_type n) const { const_iterator tmp = *this; return tmp += n; } const_iterator operator-(const difference_type n) const { const_iterator tmp = *this; return tmp -= n; } const_reference operator[](const difference_type n) const { return *(*this + n); } difference_type operator-(const const_iterator& x) const { return node == x.node ? current - x.current : BUF_SIZE *(node - x.node - 1) + (current - first)+ (x.last - x.current); } bool operator==(const const_iterator& x) const { return current == x.current; } bool operator<(const const_iterator& x) const { return(node == x.node) ? (current < x.current) : (node < x.node); } difference_type operator-(const deque::iterator& x) const { return node == x.node ? current - x.current : BUF_SIZE *(node - x.node - 1) + (current - first)+ (x.last - x.current); } bool operator==(const deque::iterator& x) const { return current == x.current; } bool operator<(const deque::iterator& x) const { return(node == x.node) ? (current < x.current) : (node < x.node); } bool operator!=(const deque::iterator& y) const { return ! (*this == y); } bool operator>(const deque::iterator& y) const { return y < *this; } bool operator<=(const deque::iterator& y) const { return ! (y < *this); } bool operator>=(const deque::iterator& y) const { return(y < *this); } bool operator!=(const const_iterator& y) const { return ! (*this == y); } bool operator>(const const_iterator& y) const { return y < *this; } bool operator<=(const const_iterator& y) const { return ! (y < *this); } bool operator>=(const const_iterator& y) const { return(y < *this); } }; // Members sorted to minimize size of class. iterator start; iterator finish; map_pointer map; size_type length; size_type map_size; allocator_type alloc; }; template static const deque::size_type deque::BUF_SIZE; template inline bool operator==(const deque& x, const deque& y) { return x.size() == y.size() && equal(x.begin(), x.end(), y.begin()); } template inline bool operator<(const deque& x, const deque& y) { return lexicographical_compare(x.begin(), x.end(), y.begin(), y.end()); } template inline bool operator!=(const deque& x, const deque& y) { return ! (x == y); } template inline bool operator>(const deque& x, const deque& y) { return(y < x); } template inline bool operator>=(const deque& x, const deque& y) { return ! (x < y); } template inline bool operator<=(const deque& x, const deque& y) { return ! (y < x); } template inline void swap(deque& x, deque& y) { x.swap(y); } template void deque::allocate_at_begin() { pointer p = alloc.allocate(BUF_SIZE); MSIPL_TRY { if (length) { if (start.node == map) { difference_type i = finish.node - start.node; size_type old_map_size = map_size; map_size = (i + 1) * 2; map_pointer tmp = map_allocator_type(alloc).allocate(map_size); copy(start.node, finish.node + 1, tmp + map_size / 4 + 1); map_allocator_type(alloc).deallocate(map, old_map_size); map = tmp; map[map_size / 4] = p; start = iterator(p + BUF_SIZE, map + map_size / 4, this); finish = iterator(finish.current, map + map_size / 4 + i + 1, this); } else { *--start.node = p; start = iterator(p + BUF_SIZE, start.node, this); } } else { map_size = 2; map = map_allocator_type(alloc).allocate(map_size); map[map_size / 2] = p; start = iterator(p + BUF_SIZE / 2 + 1, map + map_size / 2, this); finish = start; } } MSIPL_CATCH { alloc.deallocate(p, BUF_SIZE); MSIPL_RETHROW; } } template void deque::allocate_at_end() { pointer p = alloc.allocate(BUF_SIZE); MSIPL_TRY { if (length) { if (finish.node == map + map_size - 1) { difference_type i = finish.node - start.node; size_type old_map_size = map_size; map_size = (i + 1) * 2; map_pointer tmp = map_allocator_type(alloc).allocate(map_size); copy(start.node, finish.node + 1, tmp + map_size / 4); map_allocator_type(alloc).deallocate(map, old_map_size); map = tmp; map[map_size / 4 + i + 1] = p; start = iterator(start.current, map + map_size / 4, this); finish = iterator(p, map + map_size / 4 + i + 1, this); } else { *++finish.node = p; finish = iterator(p, finish.node, this); } } else { map_size = 2; map = map_allocator_type(alloc).allocate(map_size); map[map_size / 2] = p; start = iterator(p + BUF_SIZE / 2, map + map_size / 2, this); finish = start; } } MSIPL_CATCH { alloc.deallocate(p, BUF_SIZE); MSIPL_RETHROW; } } template void deque::deallocate_at_begin() { alloc.deallocate(*start.node++, BUF_SIZE); if (!length) { if (finish.current == finish.first) alloc.deallocate(*start.node, BUF_SIZE); start = iterator(this); finish = start; map_allocator_type(alloc).deallocate(map, map_size); } else start = iterator(*start.node, start.node, this); } template void deque::deallocate_at_end() { alloc.deallocate(*finish.node--, BUF_SIZE); if (!length) { start = iterator(this); finish = start; map_allocator_type(alloc).deallocate(map, map_size); } else finish = iterator(*finish.node + BUF_SIZE, finish.node, this); } template deque::deque(const deque& x) : start(this), finish(this), length(0), map(0), map_size(0), alloc(x.alloc) { const_iterator first = x.begin(); const_iterator last = x.end(); difference_type i = 0; MSIPL_TRY { for (; first != last; ++first, ++i) push_back(*first); } MSIPL_CATCH { for (difference_type j = i; j > 0; --j) pop_back(); MSIPL_RETHROW; } } template deque::~deque() { while (length) pop_front(); } template deque& deque::operator=(const deque& x) { if (this == &x) return *this; if (length >= x.length) erase(copy(x.start, x.finish, start), finish); else copy(x.start + length, x.finish, inserter(*this, copy(x.start, x.start + length, start))); return *this; } template void deque::push_front(const T& x) { bool constructed = false; bool alloc_at_begin = !length || start.current == start.first; if (alloc_at_begin) allocate_at_begin(); MSIPL_TRY { alloc.construct(start.current - 1, x); constructed = true; --start.current; ++length; //if (end().current == end().last) // this seems wrong // allocate_at_end(); } MSIPL_CATCH { if (constructed) { alloc.destroy(start.current); ++start.current; --length; } if (alloc_at_begin) deallocate_at_begin(); MSIPL_RETHROW; } } template void deque::push_back(const T& x) { bool constructed = false; if (!length) allocate_at_end(); MSIPL_TRY { alloc.construct(finish.current, x); constructed = true; ++finish.current; ++length; } MSIPL_CATCH { if (constructed) { alloc.destroy(finish.current - 1); --finish.current; --length; } if (!length) deallocate_at_end(); MSIPL_RETHROW; } if (finish.current == finish.last) allocate_at_end(); } template deque::iterator deque::insert(iterator position, const T& x) { if ( position < start || position > finish) out_of_range::__throw("Out of range exception occurred"); if (position.current == start.current) { push_front(x); return start; } else if (position.current == finish.current) { push_back(x); iterator tmp = finish; --tmp; return tmp; } else { difference_type index = position - start; difference_type remainder = length - index; if (index < remainder) { push_front(front()); iterator front1 = start; ++front1; iterator front2 = front1; ++front2; position = start + index; iterator pos1 = position; ++pos1; copy(front2, pos1, front1); } else { push_back(back()); iterator back1 = finish; --back1; iterator back2 = back1; --back2; position = start + index; copy_backward(position, back2, back1); } *position = x; return position; } } template void deque::insert(iterator position, size_type n, const T& x) { if ( position < start || position > finish) out_of_range::__throw("Out of range exception occurred"); difference_type index = position - begin(); difference_type remainder = length - index; if (remainder > index) { if (n > index) { difference_type m = n - index; MSIPL_TRY { for (; m > 0 ; --m) push_front(x); } MSIPL_CATCH { for (difference_type j = (n - index) - m; j > 0; --j) pop_front(); MSIPL_RETHROW; } difference_type i = index; MSIPL_TRY { for (; i > 0 ; --i) push_front(*(start + n -1)); } MSIPL_CATCH { for (difference_type j = index - i; j > 0; --j) pop_front(); MSIPL_RETHROW; } fill(start + n, start + n + index, x); } else { difference_type i = n; MSIPL_TRY { for (; i > 0 ; --i) push_front(*(start + n -1)); } MSIPL_CATCH { for (difference_type j = n - i; j > 0 ; --j) pop_front(); MSIPL_RETHROW; } copy(start + n + n, start + n + index, start + n); fill(start + index, start + n + index, x); } } else { difference_type orig_len = index + remainder; if (n > remainder) { difference_type m = n - remainder; MSIPL_TRY { for (; m > 0; --m) push_back(x); } MSIPL_CATCH { for (difference_type j = (n - remainder) - m; j > 0; --j) pop_back(); MSIPL_RETHROW; } difference_type i = 0; MSIPL_TRY { for (; i < remainder; ++i) push_back(*(start + index + i)); } MSIPL_CATCH { for (difference_type j = i; j > 0; --j) pop_back(); MSIPL_RETHROW; } fill(start + index, start + orig_len, x); } else { difference_type i = 0; MSIPL_TRY { for (; i < n; ++i) push_back(*(start + orig_len - n + i)); } MSIPL_CATCH { for (difference_type j = i; j > 0; --j) pop_back(); MSIPL_RETHROW; } copy_backward(start + index, start + orig_len - n, start + orig_len); fill(start + index, start + index + n, x); } } } template template void deque::_insert_iterator(iterator position, InputIterator first, InputIterator last, random_access_iterator_tag *) { if ( position < start || position > finish) out_of_range::__throw("Out of range exception occurred"); difference_type index = position - begin(); difference_type remainder = length - index; size_type n = distance(first, last); if (remainder > index) { if (n > index) { InputIterator m = last - index; cleanup c(this,true); while (m != first) { push_front(*--m); c.incr(); } difference_type i = index; while (i--) { push_front(*(start + n - 1)); c.incr(); } c.clear(); copy(last - index, last, start + n); } else { difference_type i = n; cleanup c(this,true); while (i--) { push_front(*(start + n - 1)); c.incr(); } c.clear(); copy(start + n + n, start + n + index, start + n); copy(first, last, start + index); } } else { difference_type orig_len = index + remainder; if (n > remainder) { InputIterator m = first + remainder; cleanup c(this,false); while (m != last) { push_back(*m++); c.incr(); } difference_type i = 0; while (i < remainder) { push_back(*(start + index + i++)); c.incr(); } c.clear(); copy(first, first + remainder, start + index); } else { difference_type i = 0; cleanup c(this,false); while (i < n) { push_back(*(start + orig_len - n + i++)); c.incr(); } c.clear(); copy_backward(begin() + index, start + orig_len - n, start + orig_len); copy(first, last, start + index); } } } template void deque::pop_front() { if (!length) out_of_range::__throw("Out of range exception occurred"); alloc.destroy(start.current); ++start.current; --length; if (!length || start.current == start.last) deallocate_at_begin(); } template void deque::pop_back() { if (!length) out_of_range::__throw("Out of range exception occurred"); if (finish.current == finish.first) deallocate_at_end(); --finish.current; alloc.destroy(finish.current); --length; if (!length) deallocate_at_end(); } template deque::iterator deque::erase(iterator position) { if ( position < start || position > finish) out_of_range::__throw("Out of range exception occurred"); deque::iterator iter(this); if (position != finish ) iter = position + 1; else iter = finish; if (finish - position > position - start) { copy_backward(start, position, position + 1); pop_front(); } else { copy(position + 1, finish, position); pop_back(); } return iter; } template deque::iterator deque::erase(iterator first, iterator last) { // KAI fix: Modena disallowed case first==last. if ( first > last || first < start || last > finish ) out_of_range::__throw("Out of range exception occurred"); deque::iterator iter = last; difference_type n = last - first; if ((finish - last) > (first - start)) { copy_backward(start, first, last); while (n-- > 0) pop_front(); } else { copy(last, finish, first); while (n-- > 0) pop_back(); } return iter; } } // namespace std #endif /* __KAI_DEQUE */