1*aed3e508SAndroid Build Coastguard Worker // Copyright 2011 The ChromiumOS Authors 2*aed3e508SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be 3*aed3e508SAndroid Build Coastguard Worker // found in the LICENSE file. 4*aed3e508SAndroid Build Coastguard Worker 5*aed3e508SAndroid Build Coastguard Worker #ifndef GESTURES_VECTOR_H__ 6*aed3e508SAndroid Build Coastguard Worker #define GESTURES_VECTOR_H__ 7*aed3e508SAndroid Build Coastguard Worker 8*aed3e508SAndroid Build Coastguard Worker #include <algorithm> 9*aed3e508SAndroid Build Coastguard Worker 10*aed3e508SAndroid Build Coastguard Worker #include "include/logging.h" 11*aed3e508SAndroid Build Coastguard Worker 12*aed3e508SAndroid Build Coastguard Worker namespace gestures { 13*aed3e508SAndroid Build Coastguard Worker 14*aed3e508SAndroid Build Coastguard Worker // This class allows range-based for loops to iterate over a subset of 15*aed3e508SAndroid Build Coastguard Worker // array elements, by only yielding those elements for which the 16*aed3e508SAndroid Build Coastguard Worker // AcceptMethod returns true. 17*aed3e508SAndroid Build Coastguard Worker // This class wraps around a pair of iterators, all changes to the 18*aed3e508SAndroid Build Coastguard Worker // yielded elements will modify the original array. 19*aed3e508SAndroid Build Coastguard Worker template <typename ValueType> 20*aed3e508SAndroid Build Coastguard Worker class FilteredRange { 21*aed3e508SAndroid Build Coastguard Worker public: 22*aed3e508SAndroid Build Coastguard Worker typedef bool (*AcceptMethod)(const ValueType&); 23*aed3e508SAndroid Build Coastguard Worker 24*aed3e508SAndroid Build Coastguard Worker // This class defineds a basic forward iterator that iterates over 25*aed3e508SAndroid Build Coastguard Worker // an array but skips elements for which the AcceptMethod yields false. 26*aed3e508SAndroid Build Coastguard Worker class RangeIterator { 27*aed3e508SAndroid Build Coastguard Worker public: 28*aed3e508SAndroid Build Coastguard Worker // creates a new iterator and advances to the first accepted 29*aed3e508SAndroid Build Coastguard Worker // element in the array. RangeIterator(ValueType * i,ValueType * end,AcceptMethod accept)30*aed3e508SAndroid Build Coastguard Worker RangeIterator(ValueType* i, ValueType* end, AcceptMethod accept) 31*aed3e508SAndroid Build Coastguard Worker : iter_(i), end_(end), accept_(accept) { 32*aed3e508SAndroid Build Coastguard Worker NextAcceptedIter(); 33*aed3e508SAndroid Build Coastguard Worker } 34*aed3e508SAndroid Build Coastguard Worker 35*aed3e508SAndroid Build Coastguard Worker // operator++ is required by the STL for forward iterators. 36*aed3e508SAndroid Build Coastguard Worker // Instead of advancing to the next array element, this iterator 37*aed3e508SAndroid Build Coastguard Worker // will advance to the next accepted array element 38*aed3e508SAndroid Build Coastguard Worker ValueType* operator++ () { 39*aed3e508SAndroid Build Coastguard Worker ++iter_; 40*aed3e508SAndroid Build Coastguard Worker NextAcceptedIter(); 41*aed3e508SAndroid Build Coastguard Worker return iter_; 42*aed3e508SAndroid Build Coastguard Worker } 43*aed3e508SAndroid Build Coastguard Worker 44*aed3e508SAndroid Build Coastguard Worker // operator* is required by the STL for forward iterators. 45*aed3e508SAndroid Build Coastguard Worker ValueType& operator*() { 46*aed3e508SAndroid Build Coastguard Worker return *iter_; 47*aed3e508SAndroid Build Coastguard Worker } 48*aed3e508SAndroid Build Coastguard Worker 49*aed3e508SAndroid Build Coastguard Worker // operator-> is required by the STL for forward iterators. 50*aed3e508SAndroid Build Coastguard Worker ValueType& operator->() { 51*aed3e508SAndroid Build Coastguard Worker return *iter_; 52*aed3e508SAndroid Build Coastguard Worker } 53*aed3e508SAndroid Build Coastguard Worker 54*aed3e508SAndroid Build Coastguard Worker // operator!= is required by the STL for forward iterators. 55*aed3e508SAndroid Build Coastguard Worker bool operator!= (const RangeIterator& o) { 56*aed3e508SAndroid Build Coastguard Worker return iter_ != o.iter_; 57*aed3e508SAndroid Build Coastguard Worker } 58*aed3e508SAndroid Build Coastguard Worker 59*aed3e508SAndroid Build Coastguard Worker // operator== is required by the STL for forward iterators. 60*aed3e508SAndroid Build Coastguard Worker bool operator== (const RangeIterator& o) { 61*aed3e508SAndroid Build Coastguard Worker return iter_ == o.iter_; 62*aed3e508SAndroid Build Coastguard Worker } 63*aed3e508SAndroid Build Coastguard Worker 64*aed3e508SAndroid Build Coastguard Worker private: NextAcceptedIter()65*aed3e508SAndroid Build Coastguard Worker void NextAcceptedIter() { 66*aed3e508SAndroid Build Coastguard Worker while (!accept_(*iter_) && iter_ != end_) 67*aed3e508SAndroid Build Coastguard Worker ++iter_; 68*aed3e508SAndroid Build Coastguard Worker } 69*aed3e508SAndroid Build Coastguard Worker 70*aed3e508SAndroid Build Coastguard Worker ValueType* iter_; 71*aed3e508SAndroid Build Coastguard Worker ValueType* end_; 72*aed3e508SAndroid Build Coastguard Worker AcceptMethod accept_; 73*aed3e508SAndroid Build Coastguard Worker }; 74*aed3e508SAndroid Build Coastguard Worker 75*aed3e508SAndroid Build Coastguard Worker // Create a new filtered range from begin/end pointer to an array. FilteredRange(ValueType * begin,ValueType * end,AcceptMethod accept)76*aed3e508SAndroid Build Coastguard Worker FilteredRange(ValueType* begin, ValueType* end, AcceptMethod accept) 77*aed3e508SAndroid Build Coastguard Worker : begin_(begin), end_(end), accept_(accept) {} 78*aed3e508SAndroid Build Coastguard Worker 79*aed3e508SAndroid Build Coastguard Worker // Returns a forward iterator to the first accepted element of the array. begin()80*aed3e508SAndroid Build Coastguard Worker RangeIterator begin() { 81*aed3e508SAndroid Build Coastguard Worker return RangeIterator(begin_, end_, accept_); 82*aed3e508SAndroid Build Coastguard Worker } 83*aed3e508SAndroid Build Coastguard Worker 84*aed3e508SAndroid Build Coastguard Worker // Returns an iterator to the element after the last element of the array. end()85*aed3e508SAndroid Build Coastguard Worker RangeIterator end() { 86*aed3e508SAndroid Build Coastguard Worker return RangeIterator(end_, end_, accept_); 87*aed3e508SAndroid Build Coastguard Worker } 88*aed3e508SAndroid Build Coastguard Worker 89*aed3e508SAndroid Build Coastguard Worker private: 90*aed3e508SAndroid Build Coastguard Worker ValueType* begin_; 91*aed3e508SAndroid Build Coastguard Worker ValueType* end_; 92*aed3e508SAndroid Build Coastguard Worker AcceptMethod accept_; 93*aed3e508SAndroid Build Coastguard Worker }; 94*aed3e508SAndroid Build Coastguard Worker 95*aed3e508SAndroid Build Coastguard Worker // The vector class mimicks a subset of the std::vector functionality 96*aed3e508SAndroid Build Coastguard Worker // while using a fixed size of memory to avoid calls to malloc/free. 97*aed3e508SAndroid Build Coastguard Worker // The limitations of this class are: 98*aed3e508SAndroid Build Coastguard Worker // - All insert operations might invalidate existing iterators 99*aed3e508SAndroid Build Coastguard Worker // - Currently, the ValueType type should be a POD type or aggregate of PODs, 100*aed3e508SAndroid Build Coastguard Worker // since ctors/dtors aren't called propertly on ValueType objects. 101*aed3e508SAndroid Build Coastguard Worker // - Out of range element access will always return the end() iterator 102*aed3e508SAndroid Build Coastguard Worker // and print an error, instead of throwing an exception. 103*aed3e508SAndroid Build Coastguard Worker // This class includes a non-standard extension to return a 104*aed3e508SAndroid Build Coastguard Worker // FilteredRange object iterating over the underlying array. 105*aed3e508SAndroid Build Coastguard Worker template<typename ValueType, size_t kMaxSize> 106*aed3e508SAndroid Build Coastguard Worker class vector { 107*aed3e508SAndroid Build Coastguard Worker public: 108*aed3e508SAndroid Build Coastguard Worker typedef ValueType value_type; 109*aed3e508SAndroid Build Coastguard Worker typedef ValueType* iterator; 110*aed3e508SAndroid Build Coastguard Worker typedef const ValueType* const_iterator; 111*aed3e508SAndroid Build Coastguard Worker typedef std::reverse_iterator<iterator> reverse_iterator; 112*aed3e508SAndroid Build Coastguard Worker typedef std::reverse_iterator<const_iterator> const_reverse_iterator; 113*aed3e508SAndroid Build Coastguard Worker typedef bool (*AcceptMethod)(const ValueType&); 114*aed3e508SAndroid Build Coastguard Worker vector()115*aed3e508SAndroid Build Coastguard Worker vector() : size_(0) {} vector(const vector<ValueType,kMaxSize> & that)116*aed3e508SAndroid Build Coastguard Worker vector(const vector<ValueType, kMaxSize>& that) { 117*aed3e508SAndroid Build Coastguard Worker *this = that; 118*aed3e508SAndroid Build Coastguard Worker } 119*aed3e508SAndroid Build Coastguard Worker template<size_t kThatSize> vector(const vector<ValueType,kThatSize> & that)120*aed3e508SAndroid Build Coastguard Worker vector(const vector<ValueType, kThatSize>& that) { 121*aed3e508SAndroid Build Coastguard Worker *this = that; 122*aed3e508SAndroid Build Coastguard Worker } 123*aed3e508SAndroid Build Coastguard Worker size()124*aed3e508SAndroid Build Coastguard Worker size_t size() const { return size_; } empty()125*aed3e508SAndroid Build Coastguard Worker bool empty() const { return size() == 0; } 126*aed3e508SAndroid Build Coastguard Worker 127*aed3e508SAndroid Build Coastguard Worker // methods for const element access 128*aed3e508SAndroid Build Coastguard Worker begin()129*aed3e508SAndroid Build Coastguard Worker const_iterator begin() const { return buffer_; } end()130*aed3e508SAndroid Build Coastguard Worker const_iterator end() const { return &buffer_[size_]; } rbegin()131*aed3e508SAndroid Build Coastguard Worker const_reverse_iterator rbegin() const { 132*aed3e508SAndroid Build Coastguard Worker return const_reverse_iterator(end()); 133*aed3e508SAndroid Build Coastguard Worker } rend()134*aed3e508SAndroid Build Coastguard Worker const_reverse_iterator rend() const { 135*aed3e508SAndroid Build Coastguard Worker return const_reverse_iterator(begin()); 136*aed3e508SAndroid Build Coastguard Worker } find(const ValueType & value)137*aed3e508SAndroid Build Coastguard Worker const_iterator find(const ValueType& value) const { 138*aed3e508SAndroid Build Coastguard Worker for (size_t i = 0; i < size_; ++i) 139*aed3e508SAndroid Build Coastguard Worker if (buffer_[i] == value) 140*aed3e508SAndroid Build Coastguard Worker return const_iterator(&buffer_[i]); 141*aed3e508SAndroid Build Coastguard Worker return end(); 142*aed3e508SAndroid Build Coastguard Worker } at(size_t idx)143*aed3e508SAndroid Build Coastguard Worker const ValueType& at(size_t idx) const { 144*aed3e508SAndroid Build Coastguard Worker if (idx >= size()) { 145*aed3e508SAndroid Build Coastguard Worker Err("vector::at: index out of range"); 146*aed3e508SAndroid Build Coastguard Worker idx = size() - 1; 147*aed3e508SAndroid Build Coastguard Worker } 148*aed3e508SAndroid Build Coastguard Worker return buffer_[idx]; 149*aed3e508SAndroid Build Coastguard Worker } 150*aed3e508SAndroid Build Coastguard Worker const ValueType& operator[](size_t idx) const { return buffer_[idx]; } 151*aed3e508SAndroid Build Coastguard Worker 152*aed3e508SAndroid Build Coastguard Worker // methods for non-const element access: 153*aed3e508SAndroid Build Coastguard Worker begin()154*aed3e508SAndroid Build Coastguard Worker iterator begin() { return buffer_; } end()155*aed3e508SAndroid Build Coastguard Worker iterator end() { return &buffer_[size_]; } rbegin()156*aed3e508SAndroid Build Coastguard Worker reverse_iterator rbegin() { return reverse_iterator(end()); } rend()157*aed3e508SAndroid Build Coastguard Worker reverse_iterator rend() { return reverse_iterator(begin()); } find(const ValueType & value)158*aed3e508SAndroid Build Coastguard Worker iterator find(const ValueType& value) { 159*aed3e508SAndroid Build Coastguard Worker return const_cast<iterator>( 160*aed3e508SAndroid Build Coastguard Worker const_cast<const vector<ValueType, kMaxSize>*>(this)->find(value)); 161*aed3e508SAndroid Build Coastguard Worker } at(size_t idx)162*aed3e508SAndroid Build Coastguard Worker ValueType& at(size_t idx) { 163*aed3e508SAndroid Build Coastguard Worker return const_cast<ValueType&>( 164*aed3e508SAndroid Build Coastguard Worker const_cast<const vector<ValueType, kMaxSize>*>(this)->at(idx)); 165*aed3e508SAndroid Build Coastguard Worker } 166*aed3e508SAndroid Build Coastguard Worker ValueType& operator[](size_t idx) { return buffer_[idx]; } 167*aed3e508SAndroid Build Coastguard Worker 168*aed3e508SAndroid Build Coastguard Worker // methods for inserting elements 169*aed3e508SAndroid Build Coastguard Worker // note that all these methods might invalidate existing iterators 170*aed3e508SAndroid Build Coastguard Worker push_back(const ValueType & value)171*aed3e508SAndroid Build Coastguard Worker void push_back(const ValueType& value) { 172*aed3e508SAndroid Build Coastguard Worker insert(end(), value); 173*aed3e508SAndroid Build Coastguard Worker } 174*aed3e508SAndroid Build Coastguard Worker insert(iterator position,const ValueType & value)175*aed3e508SAndroid Build Coastguard Worker iterator insert(iterator position, const ValueType& value) { 176*aed3e508SAndroid Build Coastguard Worker return insert(position, &value, (&value) + 1); 177*aed3e508SAndroid Build Coastguard Worker } 178*aed3e508SAndroid Build Coastguard Worker insert(iterator position,const_iterator first,const_iterator last)179*aed3e508SAndroid Build Coastguard Worker iterator insert(iterator position, const_iterator first, 180*aed3e508SAndroid Build Coastguard Worker const_iterator last) { 181*aed3e508SAndroid Build Coastguard Worker size_t count = last - first; 182*aed3e508SAndroid Build Coastguard Worker if (size_ + count > kMaxSize) { 183*aed3e508SAndroid Build Coastguard Worker Err("vector::insert: out of space!"); 184*aed3e508SAndroid Build Coastguard Worker return end(); 185*aed3e508SAndroid Build Coastguard Worker } 186*aed3e508SAndroid Build Coastguard Worker 187*aed3e508SAndroid Build Coastguard Worker std::copy(rbegin(), reverse_iterator(position), 188*aed3e508SAndroid Build Coastguard Worker reverse_iterator(end() + count)); 189*aed3e508SAndroid Build Coastguard Worker size_ = size_ + count; 190*aed3e508SAndroid Build Coastguard Worker std::copy(first, last, position); 191*aed3e508SAndroid Build Coastguard Worker return position; 192*aed3e508SAndroid Build Coastguard Worker } 193*aed3e508SAndroid Build Coastguard Worker 194*aed3e508SAndroid Build Coastguard Worker // methods for erasing elements 195*aed3e508SAndroid Build Coastguard Worker // note that all these methods might invalidate existing iterators 196*aed3e508SAndroid Build Coastguard Worker erase(iterator it)197*aed3e508SAndroid Build Coastguard Worker iterator erase(iterator it) { 198*aed3e508SAndroid Build Coastguard Worker return erase(it, it + 1); 199*aed3e508SAndroid Build Coastguard Worker } 200*aed3e508SAndroid Build Coastguard Worker erase(iterator first,iterator last)201*aed3e508SAndroid Build Coastguard Worker iterator erase(iterator first, iterator last) { 202*aed3e508SAndroid Build Coastguard Worker size_t count = last - first; 203*aed3e508SAndroid Build Coastguard Worker std::copy(last, end(), first); 204*aed3e508SAndroid Build Coastguard Worker for (iterator it = end() - count, e = end(); it != e; ++it) 205*aed3e508SAndroid Build Coastguard Worker (*it).~ValueType(); 206*aed3e508SAndroid Build Coastguard Worker size_ = size_ - count; 207*aed3e508SAndroid Build Coastguard Worker return first; 208*aed3e508SAndroid Build Coastguard Worker } 209*aed3e508SAndroid Build Coastguard Worker clear()210*aed3e508SAndroid Build Coastguard Worker void clear() { 211*aed3e508SAndroid Build Coastguard Worker erase(begin(), end()); 212*aed3e508SAndroid Build Coastguard Worker } 213*aed3e508SAndroid Build Coastguard Worker 214*aed3e508SAndroid Build Coastguard Worker template<size_t kThatSize> 215*aed3e508SAndroid Build Coastguard Worker vector<ValueType, kMaxSize>& operator=( 216*aed3e508SAndroid Build Coastguard Worker const vector<ValueType, kThatSize>& that) { 217*aed3e508SAndroid Build Coastguard Worker clear(); 218*aed3e508SAndroid Build Coastguard Worker insert(begin(), that.begin(), that.end()); 219*aed3e508SAndroid Build Coastguard Worker return *this; 220*aed3e508SAndroid Build Coastguard Worker } 221*aed3e508SAndroid Build Coastguard Worker 222*aed3e508SAndroid Build Coastguard Worker private: 223*aed3e508SAndroid Build Coastguard Worker ValueType buffer_[kMaxSize]; 224*aed3e508SAndroid Build Coastguard Worker size_t size_; 225*aed3e508SAndroid Build Coastguard Worker }; 226*aed3e508SAndroid Build Coastguard Worker 227*aed3e508SAndroid Build Coastguard Worker } // namespace gestures 228*aed3e508SAndroid Build Coastguard Worker 229*aed3e508SAndroid Build Coastguard Worker #endif // GESTURES_VECTOR_H__ 230