Files
NE_YuR/openflow/include/click/deque.hh

688 lines
18 KiB
C++

#ifndef CLICK_DEQUE_HH
#define CLICK_DEQUE_HH 1
#include <click/algorithm.hh>
#include <click/array_memory.hh>
CLICK_DECLS
/** @cond never */
template <typename AM> class deque_memory { public:
typedef int size_type;
typedef typename AM::type type;
inline bool need_argument_copy(const type *argp) const {
return fast_argument<type>::is_reference && (uintptr_t) argp - (uintptr_t) l_ < (size_t) (capacity_ * sizeof(type));
}
inline size_type canonp(size_type p) const {
return p < capacity_ ? p : p - capacity_;
}
inline size_type i2p(size_type i) const {
return canonp(head_ + i);
}
inline size_type prevp(size_type p) const {
return p ? p - 1 : capacity_ - 1;
}
inline size_type nextp(size_type p) const {
return p + 1 != capacity_ ? p + 1 : 0;
}
inline size_type naccess(size_type n) const {
return head_ + n <= capacity_ ? n : capacity_ - head_;
}
deque_memory()
: l_(0), head_(0), n_(0), capacity_(0) {
}
~deque_memory();
void assign(const deque_memory<AM> &x);
void assign(size_type n, const type *vp);
void resize(size_type n, const type *vp);
bool insert(int i, const type *vp);
int erase(int ai, int bi);
inline void push_back(const type *vp) {
if (n_ < capacity_) {
size_type p = i2p(n_);
AM::mark_undefined(l_ + p, 1);
AM::fill(l_ + p, 1, vp);
++n_;
} else
reserve_and_push(-1, false, vp);
}
#if HAVE_CXX_RVALUE_REFERENCES
inline void move_construct_back(type* vp) {
if (n_ < capacity_) {
size_type p = i2p(n_);
AM::mark_undefined(l_ + p, 1);
AM::move_construct(l_ + p, vp);
++n_;
} else
reserve_and_push(-1, false, vp);
}
#endif
inline void pop_back() {
assert(n_ > 0);
--n_;
size_type p = i2p(n_);
AM::destroy(l_ + p, 1);
AM::mark_noaccess(l_ + p, 1);
}
inline void push_front(const type *vp) {
if (n_ < capacity_) {
head_ = prevp(head_);
AM::mark_undefined(l_ + head_, 1);
AM::fill(l_ + head_, 1, vp);
++n_;
} else
reserve_and_push(-1, true, vp);
}
#if HAVE_CXX_RVALUE_REFERENCES
inline void move_construct_front(type* vp) {
if (n_ < capacity_) {
head_ = prevp(head_);
AM::mark_undefined(l_ + head_, 1);
AM::move_construct(l_ + head_, vp);
++n_;
} else
reserve_and_push(-1, true, vp);
}
#endif
inline void pop_front() {
assert(n_ > 0);
--n_;
AM::destroy(l_ + head_, 1);
AM::mark_noaccess(l_ + head_, 1);
head_ = nextp(head_);
}
inline void clear() {
size_type f = naccess(n_);
AM::destroy(l_ + head_, f);
AM::destroy(l_, n_ - f);
AM::mark_noaccess(l_, capacity_);
head_ = n_ = 0;
}
bool reserve_and_push(size_type n, bool isfront, const type *vp);
void swap(deque_memory<AM> &x);
type *l_;
size_type head_;
size_type n_;
size_type capacity_;
};
/** @endcond never */
template <typename T> class Deque_iterator;
template <typename T> class Deque_const_iterator;
/** @class Deque
@brief Deque template.
Deque implements a double-ended queue: a growable array that can efficiently
add and remove elements at both ends (see push_back(), pop_back(),
push_front(), and pop_front()). Its interface should be compatible with
C++'s std::deque, although that type has more methods. Deque elements are
accessed with operator[] like arrays.
Deque is implemented using a circular buffer of elements. This makes its
operations slightly slower than those of Vector. If you only need to push
elements to the end of an array, prefer Vector.
Example code:
@code
Deque<int> d;
printf("%d\n", d.size()); // prints "0"
d.push_back(1);
d.push_back(2);
printf("%d\n", d.size()); // prints "2"
printf("%d %d\n", d[0], d[1]); // prints "1 2"
d.push_front(0);
d.push_front(-1);
printf("%d\n", d.size()); // prints "4"
printf("%d %d %d %d\n", d[0], d[1], d[2], d[3]);
// prints "-1 0 1 2"
d.pop_front();
d.pop_back();
printf("%d\n", d.size()); // prints "2"
printf("%d %d\n", d[0], d[1]); // prints "0 1"
@endcode
*/
template <typename T>
class Deque {
typedef typename array_memory<T>::type array_memory_type;
mutable deque_memory<array_memory_type> vm_;
public:
typedef T value_type; ///< Value type.
typedef T &reference; ///< Reference to value type.
typedef const T &const_reference; ///< Const reference to value type.
typedef T *pointer; ///< Pointer to value type.
typedef const T *const_pointer; ///< Pointer to const value type.
/** @brief Type used for value arguments (either T or const T &). */
typedef typename fast_argument<T>::type value_argument_type;
typedef const T &const_access_type;
typedef int size_type; ///< Type of sizes (size()).
typedef Deque_iterator<T> iterator; ///< Iterator type.
typedef Deque_const_iterator<T> const_iterator; ///< Const iterator type.
/** @brief Constant passed to reserve() to grow the deque. */
enum { RESERVE_GROW = (size_type) -1 };
explicit inline Deque();
explicit inline Deque(size_type n, value_argument_type v);
inline Deque(const Deque<T> &x);
#if HAVE_CXX_RVALUE_REFERENCES
inline Deque(Deque<T> &&x);
#endif
inline Deque<T> &operator=(const Deque<T> &x);
#if HAVE_CXX_RVALUE_REFERENCES
inline Deque<T> &operator=(Deque<T> &&x);
#endif
inline Deque<T> &assign(size_type n, value_argument_type v = T());
inline iterator begin();
inline iterator end();
inline const_iterator begin() const;
inline const_iterator end() const;
inline const_iterator cbegin() const;
inline const_iterator cend() const;
inline size_type size() const;
inline size_type capacity() const;
inline bool empty() const;
inline void resize(size_type n, value_argument_type v = T());
inline bool reserve(size_type n);
inline T &operator[](size_type i);
inline const T &operator[](size_type i) const;
inline T &at(size_type i);
inline const T &at(size_type i) const;
inline T &front();
inline const T &front() const;
inline T &back();
inline const T &back() const;
inline T &unchecked_at(size_type i);
inline const T &unchecked_at(size_type i) const;
inline T &at_u(size_type i) CLICK_DEPRECATED;
inline const T &at_u(size_type i) const CLICK_DEPRECATED;
inline void push_back(value_argument_type v);
#if HAVE_CXX_RVALUE_REFERENCES
template <typename A = fast_argument<T> >
inline typename A::enable_rvalue_reference push_back(T &&v);
#endif
inline void pop_back();
inline void push_front(value_argument_type v);
#if HAVE_CXX_RVALUE_REFERENCES
template <typename A = fast_argument<T> >
inline typename A::enable_rvalue_reference push_front(T &&v);
#endif
inline void pop_front();
inline iterator insert(iterator it, value_argument_type v);
inline iterator erase(iterator it);
inline iterator erase(iterator a, iterator b);
inline void clear();
inline void swap(Deque<T> &x);
};
template <typename T>
class Deque_const_iterator {
const Deque<T> *q_;
typename Deque<T>::size_type p_;
friend class Deque<T>;
public:
typedef typename Deque<T>::size_type size_type;
typedef Deque_const_iterator<T> const_iterator;
typedef Deque_iterator<T> iterator;
Deque_const_iterator() {
}
Deque_const_iterator(const Deque<T> *q, size_type p)
: q_(q), p_(p) {
}
const T *operator->() const {
return &(*q_)[p_];
}
const T &operator*() const {
return (*q_)[p_];
}
const T &operator[](size_type i) const {
return (*q_)[p_ + i];
}
bool operator==(const const_iterator &x) const {
return p_ == x.p_ && q_ == x.q_;
}
bool operator!=(const const_iterator &x) const {
return p_ != x.p_ || q_ != x.q_;
}
bool operator<(const const_iterator &x) const {
assert(q_ == x.q_);
return p_ < x.p_;
}
bool operator<=(const const_iterator &x) const {
assert(q_ == x.q_);
return p_ <= x.p_;
}
bool operator>=(const const_iterator &x) const {
assert(q_ == x.q_);
return p_ >= x.p_;
}
bool operator>(const const_iterator &x) const {
assert(q_ == x.q_);
return p_ > x.p_;
}
size_type diff(const const_iterator &x) const {
assert(q_ == x.q_);
return p_ - x.p_;
}
void operator++(int) {
++p_;
}
const_iterator &operator++() {
++p_;
return *this;
}
void operator--(int) {
--p_;
}
const_iterator &operator--() {
--p_;
return *this;
}
const_iterator &operator+=(size_type n) {
p_ += n;
return *this;
}
const_iterator &operator-=(size_type n) {
p_ -= n;
return *this;
}
};
template <typename T>
class Deque_iterator : public Deque_const_iterator<T> { public:
typedef typename Deque<T>::size_type size_type;
typedef Deque_const_iterator<T> const_iterator;
typedef Deque_iterator<T> iterator;
Deque_iterator() {
}
Deque_iterator(Deque<T> *q, int p)
: const_iterator(q, p) {
}
T *operator->() const {
return const_cast<T *>(const_iterator::operator->());
}
T &operator*() const {
return const_cast<T &>(const_iterator::operator*());
}
T &operator[](int n) const {
return const_cast<T &>(const_iterator::operator[](n));
}
iterator &operator+=(size_type n) {
const_iterator::operator+=(n);
return *this;
}
iterator &operator-=(size_type n) {
const_iterator::operator-=(n);
return *this;
}
};
/** @brief Construct an empty deque. */
template <typename T>
inline Deque<T>::Deque() {
}
/** @brief Construct a deque containing @a n copies of @a v. */
template <typename T>
inline Deque<T>::Deque(size_type n, value_argument_type v) {
vm_.resize(n, array_memory_type::cast(&v));
}
/** @brief Construct a deque as a copy of @a x. */
template <typename T>
inline Deque<T>::Deque(const Deque<T> &x) {
vm_.assign(x.vm_);
}
#if HAVE_CXX_RVALUE_REFERENCES
/** @brief Construct a deque as a copy of @a x. */
template <typename T>
inline Deque<T>::Deque(Deque<T> &&x) {
vm_.assign(x.vm_);
}
#endif
/** @brief Return the number of elements. */
template <typename T>
inline typename Deque<T>::size_type Deque<T>::size() const {
return vm_.n_;
}
/** @brief Test if the deque is empty (size() == 0). */
template <typename T>
inline bool Deque<T>::empty() const {
return vm_.n_ == 0;
}
/** @brief Return the deque's capacity.
The capacity is greater than or equal to the size(). Functions such as
resize(n) will not allocate new memory for the deque if n <=
capacity(). */
template <typename T>
inline typename Deque<T>::size_type Deque<T>::capacity() const {
return vm_.capacity_;
}
/** @brief Return an iterator for the first element in the deque. */
template <typename T>
inline typename Deque<T>::iterator Deque<T>::begin() {
return iterator(this, 0);
}
/** @overload */
template <typename T>
inline typename Deque<T>::const_iterator Deque<T>::begin() const {
return const_iterator(this, 0);
}
/** @brief Return an iterator for the end of the deque.
@invariant end() == begin() + size() */
template <typename T>
inline typename Deque<T>::iterator Deque<T>::end() {
return iterator(this, vm_.n_);
}
/** @overload */
template <typename T>
inline typename Deque<T>::const_iterator Deque<T>::end() const {
return const_iterator(this, vm_.n_);
}
/** @brief Return a const_iterator for the beginning of the deque. */
template <typename T>
inline typename Deque<T>::const_iterator Deque<T>::cbegin() const {
return const_iterator(this, 0);
}
/** @brief Return a const_iterator for the end of the deque.
@invariant end() == begin() + size() */
template <typename T>
inline typename Deque<T>::const_iterator Deque<T>::cend() const {
return const_iterator(this, vm_.n_);
}
/** @brief Return a reference to the <em>i</em>th element.
@pre 0 <= @a i < size() */
template <typename T>
inline T &Deque<T>::operator[](size_type i) {
assert((unsigned) i < (unsigned) vm_.n_);
return *(T *)&vm_.l_[vm_.i2p(i)];
}
/** @overload */
template <typename T>
inline const T &Deque<T>::operator[](size_type i) const {
assert((unsigned) i < (unsigned) vm_.n_);
return *(T *)&vm_.l_[vm_.i2p(i)];
}
/** @brief Return a reference to the <em>i</em>th element.
@pre 0 <= @a i < size()
@sa operator[]() */
template <typename T>
inline T &Deque<T>::at(size_type i) {
return operator[](i);
}
/** @overload */
template <typename T>
inline const T &Deque<T>::at(size_type i) const {
return operator[](i);
}
/** @brief Return a reference to the first element.
@pre !empty() */
template <typename T>
inline T &Deque<T>::front() {
return operator[](0);
}
/** @overload */
template <typename T>
inline const T &Deque<T>::front() const {
return operator[](0);
}
/** @brief Return a reference to the last element (number size()-1).
@pre !empty() */
template <typename T>
inline T &Deque<T>::back() {
return operator[](vm_.n_ - 1);
}
/** @overload */
template <typename T>
inline const T &Deque<T>::back() const {
return operator[](vm_.n_ - 1);
}
/** @brief Return a reference to the <em>i</em>th element.
@pre 0 <= @a i < size()
Unlike operator[]() and at(), this function does not check bounds,
even if assertions are enabled. Use with caution. */
template <typename T>
inline T &Deque<T>::unchecked_at(size_type i) {
return *(T *)&vm_.l_[vm_.i2p(i)];
}
/** @overload */
template <typename T>
inline const T &Deque<T>::unchecked_at(size_type i) const {
return *(T *)&vm_.l_[vm_.i2p(i)];
}
/** @cond never */
template <typename T>
inline T &Deque<T>::at_u(size_type i) {
return unchecked_at(i);
}
template <typename T>
inline const T &Deque<T>::at_u(size_type i) const {
return unchecked_at(i);
}
/** @endcond never */
/** @brief Resize the deque to contain @a n elements.
@param n new size
@param v value used to fill new elements */
template <typename T>
inline void Deque<T>::resize(size_type n, value_argument_type v) {
vm_.resize(n, array_memory_type::cast(&v));
}
/** @brief Append @a v to the end of the deque.
A copy of @a v is added to position size(). Takes amortized O(1)
time. */
template <typename T>
inline void Deque<T>::push_back(value_argument_type v) {
vm_.push_back(array_memory_type::cast(&v));
}
#if HAVE_CXX_RVALUE_REFERENCES
/** @overload */
template <typename T> template <typename A>
inline typename A::enable_rvalue_reference Deque<T>::push_back(T&& v) {
vm_.move_construct_back(array_memory_type::cast(&v));
}
#endif
/** @brief Remove the last element.
Takes O(1) time. */
template <typename T>
inline void Deque<T>::pop_back() {
vm_.pop_back();
}
/** @brief Prepend element @a v.
A copy of @a v is added to position 0. Other elements are shifted one
position forward. Takes amortized O(1) time. */
template <typename T>
inline void Deque<T>::push_front(value_argument_type v) {
vm_.push_front(array_memory_type::cast(&v));
}
#if HAVE_CXX_RVALUE_REFERENCES
/** @overload */
template <typename T> template <typename A>
inline typename A::enable_rvalue_reference Deque<T>::push_front(T&& v) {
vm_.move_construct_front(array_memory_type::cast(&v));
}
#endif
/** @brief Remove the first element.
Other elements are shifted one position backward. Takes O(1) time. */
template <typename T>
inline void Deque<T>::pop_front() {
vm_.pop_front();
}
/** @brief Insert @a v before position @a it.
@return An iterator pointing at the new element. */
template <typename T>
inline typename Deque<T>::iterator
Deque<T>::insert(iterator it, value_argument_type v) {
assert(it.q_ == this);
if (likely(vm_.insert(it.p_, array_memory_type::cast(&v))))
return it;
else
return end();
}
/** @brief Remove the element at position @a it.
@return An iterator pointing at the element following @a it. */
template <typename T>
inline typename Deque<T>::iterator
Deque<T>::erase(iterator it) {
assert(it.q_ == this);
return (it < end() ? erase(it, it + 1) : it);
}
/** @brief Remove the elements in [@a a, @a b).
@return An iterator corresponding to @a b. */
template <typename T>
inline typename Deque<T>::iterator
Deque<T>::erase(iterator a, iterator b) {
assert(a.q_ == this && b.q_ == this);
return iterator(this, vm_.erase(a.p_, b.p_));
}
/** @brief Remove all elements.
@post size() == 0 */
template <typename T>
inline void Deque<T>::clear() {
vm_.clear();
}
/** @brief Reserve space for at least @a n more elements.
@return true iff reserve succeeded.
This function changes the deque's capacity(), not its size(). If
reserve(@a n) succeeds, then any succeeding call to resize(@a m) with @a
m < @a n will succeed without allocating deque memory. */
template <typename T>
inline bool Deque<T>::reserve(size_type n) {
return vm_.reserve_and_push(n, false, 0);
}
/** @brief Swap the contents of this deque and @a x. */
template <typename T>
inline void Deque<T>::swap(Deque<T> &x) {
vm_.swap(x.vm_);
}
/** @brief Replace this deque's contents with a copy of @a x. */
template <typename T>
inline Deque<T> &Deque<T>::operator=(const Deque<T> &x) {
vm_.assign(x.vm_);
return *this;
}
#if HAVE_CXX_RVALUE_REFERENCES
/** @brief Replace this deque's contents with those of @a x. */
template <typename T>
inline Deque<T> &Deque<T>::operator=(Deque<T> &&x) {
vm_.swap(x.vm_);
return *this;
}
#endif
/** @brief Replace this deque's contents with @a n copies of @a v.
@post size() == @a n */
template <typename T>
inline Deque<T> &Deque<T>::assign(size_type n, value_argument_type v) {
vm_.assign(n, array_memory_type::cast(&v));
return *this;
}
template <typename T>
Deque_const_iterator<T> operator+(Deque_const_iterator<T> it,
typename Deque<T>::size_type n) {
return it += n;
}
template <typename T>
Deque_const_iterator<T> operator-(Deque_const_iterator<T> it,
typename Deque<T>::size_type n) {
return it -= n;
}
template <typename T>
Deque_iterator<T> operator+(Deque_iterator<T> it,
typename Deque<T>::size_type n) {
return it += n;
}
template <typename T>
Deque_iterator<T> operator-(Deque_iterator<T> it,
typename Deque<T>::size_type n) {
return it -= n;
}
template <typename T>
typename Deque_const_iterator<T>::size_type
operator-(const Deque_const_iterator<T> &a, const Deque_const_iterator<T> &b) {
return a.diff(b);
}
template <typename T>
inline void click_swap(Deque<T> &a, Deque<T> &b) {
a.swap(b);
}
template <typename T>
inline void assign_consume(Deque<T> &a, Deque<T> &b) {
a.swap(b);
}
CLICK_ENDDECLS
#include <click/deque.cc>
#endif