Page Speed Optimization Libraries
1.3.25.1
|
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 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_