00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00018
00019 #ifndef NET_INSTAWEB_UTIL_PUBLIC_VECTOR_DEQUE_H_
00020 #define NET_INSTAWEB_UTIL_PUBLIC_VECTOR_DEQUE_H_
00021
00022 #include <cstddef>
00023 #include <cstring>
00024
00025 #include "net/instaweb/util/public/basictypes.h"
00026
00045 template<class T> class VectorDeque {
00046 public:
00049 VectorDeque()
00050 : start_position_(0),
00051 size_minus_1_(static_cast<size_t>(-1)),
00052 capacity_minus_1_(initial_capacity() - 1),
00053 data_(new T[initial_capacity()]) {
00054 }
00055 ~VectorDeque() {
00056 delete [] data_;
00057 data_ = NULL;
00058 }
00059
00060 static size_t initial_capacity() { return 4; }
00061
00062 void push_back(T value) {
00063 ExpandIfNecessary();
00064 ++size_minus_1_;
00065 *PointerAt(size_minus_1_) = value;
00066 }
00067
00071 # define SPECIAL_CASE_POINTER_AT_0 1
00072
00073 void push_front(T value) {
00074 ExpandIfNecessary();
00075 start_position_ = ModCapacity(start_position_ - 1);
00076 # if SPECIAL_CASE_POINTER_AT_0
00077 *PointerAt0() = value;
00078 # else
00079 *PointerAt(0) = value;
00080 # endif
00081 ++size_minus_1_;
00082 }
00083
00084 void pop_back() {
00085 --size_minus_1_;
00086 }
00087
00088 void pop_front() {
00089 start_position_ = ModCapacity(start_position_ + 1);
00090 --size_minus_1_;
00091 }
00092
00093 T back() const {
00094 return *PointerAt(size_minus_1_);
00095 }
00096
00097 T front() const {
00098 # if SPECIAL_CASE_POINTER_AT_0
00099 return *PointerAt0();
00100 # else
00101 return *PointerAt(0);
00102 # endif
00103 }
00104
00105 size_t capacity() const { return capacity_minus_1_ + 1; }
00106 size_t size() const { return size_minus_1_ + 1; }
00107 bool empty() const { return size_minus_1_ == static_cast<size_t>(-1); }
00108
00109 private:
00114 size_t ModCapacity(size_t index) const { return index & capacity_minus_1_; }
00115
00117 T* PointerAt(size_t position) {
00118 return data_ + ModCapacity(start_position_ + position);
00119 }
00120
00121 const T* PointerAt(size_t position) const {
00122 return data_ + ModCapacity(start_position_ + position);
00123 }
00124
00125 # if SPECIAL_CASE_POINTER_AT_0
00126 T* PointerAt0() {
00127 return data_ + start_position_;
00128 }
00129
00130 const T* PointerAt0() const {
00131 return data_ + start_position_;
00132 }
00133 # endif
00134 # undef SPECIAL_CASE_POINTER_AT_0
00135
00138 void ExpandIfNecessary() {
00140 if (size_minus_1_ == capacity_minus_1_) {
00163 capacity_minus_1_ = 2 * capacity() - 1;
00164 T* old_data = data_;
00165 data_ = new T[capacity()];
00166 size_t sz = size();
00167 if (start_position_ == 0) {
00168 memcpy(data_, old_data, sz * sizeof(*data_));
00169 } else {
00172 memcpy(data_, old_data, start_position_ * sizeof(*data_));
00173 size_t size_of_right_chunk = sz - start_position_;
00174 size_t new_start_position = start_position_ + sz;
00175 memcpy(data_ + new_start_position,
00176 old_data + start_position_,
00177 size_of_right_chunk * sizeof(*data_));
00178 start_position_ = new_start_position;
00179 }
00180 delete [] old_data;
00181 }
00182 }
00183
00184 size_t start_position_;
00185 size_t size_minus_1_;
00186 size_t capacity_minus_1_;
00187 T* data_;
00188
00189 DISALLOW_COPY_AND_ASSIGN(VectorDeque);
00190 };
00191
00192 #endif ///< NET_INSTAWEB_UTIL_PUBLIC_VECTOR_DEQUE_H_