xref: /aosp_15_r20/external/libchrome-gestures/include/vector.h (revision aed3e5085e770be5b69ce25295ecf6ddf906af95)
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