Page Speed Optimization Libraries
1.5.27.2
|
00001 /* 00002 * Copyright 2012 Google Inc. 00003 * 00004 * Licensed under the Apache License, Version 2.0 (the "License"); 00005 * you may not use this file except in compliance with the License. 00006 * You may obtain a copy of the License at 00007 * 00008 * http:///www.apache.org/licenses/LICENSE-2.0 00009 * 00010 * Unless required by applicable law or agreed to in writing, software 00011 * distributed under the License is distributed on an "AS IS" BASIS, 00012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00013 * See the License for the specific language governing permissions and 00014 * limitations under the License. 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 00027 namespace net_instaweb { 00028 00047 template<class T> class VectorDeque { 00048 public: 00051 VectorDeque() 00052 : start_position_(0), 00053 size_minus_1_(static_cast<size_t>(-1)), 00054 capacity_minus_1_(initial_capacity() - 1), 00055 data_(new T[initial_capacity()]) { 00056 } 00057 ~VectorDeque() { 00058 delete [] data_; 00059 data_ = NULL; 00060 } 00061 00062 static size_t initial_capacity() { return 4; } 00063 00064 void push_back(T value) { 00065 ExpandIfNecessary(); 00066 ++size_minus_1_; 00067 *PointerAt(size_minus_1_) = value; 00068 } 00069 00073 # define SPECIAL_CASE_POINTER_AT_0 1 00074 00075 void push_front(T value) { 00076 ExpandIfNecessary(); 00077 start_position_ = ModCapacity(start_position_ - 1); 00078 # if SPECIAL_CASE_POINTER_AT_0 00079 *PointerAt0() = value; 00080 # else 00081 *PointerAt(0) = value; 00082 # endif 00083 ++size_minus_1_; 00084 } 00085 00086 void pop_back() { 00087 --size_minus_1_; 00088 } 00089 00090 void pop_front() { 00091 start_position_ = ModCapacity(start_position_ + 1); 00092 --size_minus_1_; 00093 } 00094 00095 T back() const { 00096 return *PointerAt(size_minus_1_); 00097 } 00098 00099 T front() const { 00100 # if SPECIAL_CASE_POINTER_AT_0 00101 return *PointerAt0(); 00102 # else 00103 return *PointerAt(0); 00104 # endif 00105 } 00106 00107 size_t capacity() const { return capacity_minus_1_ + 1; } 00108 size_t size() const { return size_minus_1_ + 1; } 00109 bool empty() const { return size_minus_1_ == static_cast<size_t>(-1); } 00110 00111 private: 00116 size_t ModCapacity(size_t index) const { return index & capacity_minus_1_; } 00117 00119 T* PointerAt(size_t position) { 00120 return data_ + ModCapacity(start_position_ + position); 00121 } 00122 00123 const T* PointerAt(size_t position) const { 00124 return data_ + ModCapacity(start_position_ + position); 00125 } 00126 00127 # if SPECIAL_CASE_POINTER_AT_0 00128 T* PointerAt0() { 00129 return data_ + start_position_; 00130 } 00131 00132 const T* PointerAt0() const { 00133 return data_ + start_position_; 00134 } 00135 # endif 00136 # undef SPECIAL_CASE_POINTER_AT_0 00137 00140 void ExpandIfNecessary() { 00142 if (size_minus_1_ == capacity_minus_1_) { 00165 capacity_minus_1_ = 2 * capacity() - 1; 00166 T* old_data = data_; 00167 data_ = new T[capacity()]; 00168 size_t sz = size(); 00169 if (start_position_ == 0) { 00170 memcpy(data_, old_data, sz * sizeof(*data_)); 00171 } else { 00174 memcpy(data_, old_data, start_position_ * sizeof(*data_)); 00175 size_t size_of_right_chunk = sz - start_position_; 00176 size_t new_start_position = start_position_ + sz; 00177 memcpy(data_ + new_start_position, 00178 old_data + start_position_, 00179 size_of_right_chunk * sizeof(*data_)); 00180 start_position_ = new_start_position; 00181 } 00182 delete [] old_data; 00183 } 00184 } 00185 00186 size_t start_position_; 00187 size_t size_minus_1_; 00188 size_t capacity_minus_1_; 00189 T* data_; 00190 00191 DISALLOW_COPY_AND_ASSIGN(VectorDeque); 00192 }; 00193 00194 } 00195 00196 #endif ///< NET_INSTAWEB_UTIL_PUBLIC_VECTOR_DEQUE_H_