230 lines
6.7 KiB
C++
230 lines
6.7 KiB
C++
// Copyright 2011 The ChromiumOS Authors
|
|
// Use of this source code is governed by a BSD-style license that can be
|
|
// found in the LICENSE file.
|
|
|
|
#ifndef GESTURES_VECTOR_H__
|
|
#define GESTURES_VECTOR_H__
|
|
|
|
#include <algorithm>
|
|
|
|
#include "include/logging.h"
|
|
|
|
namespace gestures {
|
|
|
|
// This class allows range-based for loops to iterate over a subset of
|
|
// array elements, by only yielding those elements for which the
|
|
// AcceptMethod returns true.
|
|
// This class wraps around a pair of iterators, all changes to the
|
|
// yielded elements will modify the original array.
|
|
template <typename ValueType>
|
|
class FilteredRange {
|
|
public:
|
|
typedef bool (*AcceptMethod)(const ValueType&);
|
|
|
|
// This class defineds a basic forward iterator that iterates over
|
|
// an array but skips elements for which the AcceptMethod yields false.
|
|
class RangeIterator {
|
|
public:
|
|
// creates a new iterator and advances to the first accepted
|
|
// element in the array.
|
|
RangeIterator(ValueType* i, ValueType* end, AcceptMethod accept)
|
|
: iter_(i), end_(end), accept_(accept) {
|
|
NextAcceptedIter();
|
|
}
|
|
|
|
// operator++ is required by the STL for forward iterators.
|
|
// Instead of advancing to the next array element, this iterator
|
|
// will advance to the next accepted array element
|
|
ValueType* operator++ () {
|
|
++iter_;
|
|
NextAcceptedIter();
|
|
return iter_;
|
|
}
|
|
|
|
// operator* is required by the STL for forward iterators.
|
|
ValueType& operator*() {
|
|
return *iter_;
|
|
}
|
|
|
|
// operator-> is required by the STL for forward iterators.
|
|
ValueType& operator->() {
|
|
return *iter_;
|
|
}
|
|
|
|
// operator!= is required by the STL for forward iterators.
|
|
bool operator!= (const RangeIterator& o) {
|
|
return iter_ != o.iter_;
|
|
}
|
|
|
|
// operator== is required by the STL for forward iterators.
|
|
bool operator== (const RangeIterator& o) {
|
|
return iter_ == o.iter_;
|
|
}
|
|
|
|
private:
|
|
void NextAcceptedIter() {
|
|
while (!accept_(*iter_) && iter_ != end_)
|
|
++iter_;
|
|
}
|
|
|
|
ValueType* iter_;
|
|
ValueType* end_;
|
|
AcceptMethod accept_;
|
|
};
|
|
|
|
// Create a new filtered range from begin/end pointer to an array.
|
|
FilteredRange(ValueType* begin, ValueType* end, AcceptMethod accept)
|
|
: begin_(begin), end_(end), accept_(accept) {}
|
|
|
|
// Returns a forward iterator to the first accepted element of the array.
|
|
RangeIterator begin() {
|
|
return RangeIterator(begin_, end_, accept_);
|
|
}
|
|
|
|
// Returns an iterator to the element after the last element of the array.
|
|
RangeIterator end() {
|
|
return RangeIterator(end_, end_, accept_);
|
|
}
|
|
|
|
private:
|
|
ValueType* begin_;
|
|
ValueType* end_;
|
|
AcceptMethod accept_;
|
|
};
|
|
|
|
// The vector class mimicks a subset of the std::vector functionality
|
|
// while using a fixed size of memory to avoid calls to malloc/free.
|
|
// The limitations of this class are:
|
|
// - All insert operations might invalidate existing iterators
|
|
// - Currently, the ValueType type should be a POD type or aggregate of PODs,
|
|
// since ctors/dtors aren't called propertly on ValueType objects.
|
|
// - Out of range element access will always return the end() iterator
|
|
// and print an error, instead of throwing an exception.
|
|
// This class includes a non-standard extension to return a
|
|
// FilteredRange object iterating over the underlying array.
|
|
template<typename ValueType, size_t kMaxSize>
|
|
class vector {
|
|
public:
|
|
typedef ValueType value_type;
|
|
typedef ValueType* iterator;
|
|
typedef const ValueType* const_iterator;
|
|
typedef std::reverse_iterator<iterator> reverse_iterator;
|
|
typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
|
|
typedef bool (*AcceptMethod)(const ValueType&);
|
|
|
|
vector() : size_(0) {}
|
|
vector(const vector<ValueType, kMaxSize>& that) {
|
|
*this = that;
|
|
}
|
|
template<size_t kThatSize>
|
|
vector(const vector<ValueType, kThatSize>& that) {
|
|
*this = that;
|
|
}
|
|
|
|
size_t size() const { return size_; }
|
|
bool empty() const { return size() == 0; }
|
|
|
|
// methods for const element access
|
|
|
|
const_iterator begin() const { return buffer_; }
|
|
const_iterator end() const { return &buffer_[size_]; }
|
|
const_reverse_iterator rbegin() const {
|
|
return const_reverse_iterator(end());
|
|
}
|
|
const_reverse_iterator rend() const {
|
|
return const_reverse_iterator(begin());
|
|
}
|
|
const_iterator find(const ValueType& value) const {
|
|
for (size_t i = 0; i < size_; ++i)
|
|
if (buffer_[i] == value)
|
|
return const_iterator(&buffer_[i]);
|
|
return end();
|
|
}
|
|
const ValueType& at(size_t idx) const {
|
|
if (idx >= size()) {
|
|
Err("vector::at: index out of range");
|
|
idx = size() - 1;
|
|
}
|
|
return buffer_[idx];
|
|
}
|
|
const ValueType& operator[](size_t idx) const { return buffer_[idx]; }
|
|
|
|
// methods for non-const element access:
|
|
|
|
iterator begin() { return buffer_; }
|
|
iterator end() { return &buffer_[size_]; }
|
|
reverse_iterator rbegin() { return reverse_iterator(end()); }
|
|
reverse_iterator rend() { return reverse_iterator(begin()); }
|
|
iterator find(const ValueType& value) {
|
|
return const_cast<iterator>(
|
|
const_cast<const vector<ValueType, kMaxSize>*>(this)->find(value));
|
|
}
|
|
ValueType& at(size_t idx) {
|
|
return const_cast<ValueType&>(
|
|
const_cast<const vector<ValueType, kMaxSize>*>(this)->at(idx));
|
|
}
|
|
ValueType& operator[](size_t idx) { return buffer_[idx]; }
|
|
|
|
// methods for inserting elements
|
|
// note that all these methods might invalidate existing iterators
|
|
|
|
void push_back(const ValueType& value) {
|
|
insert(end(), value);
|
|
}
|
|
|
|
iterator insert(iterator position, const ValueType& value) {
|
|
return insert(position, &value, (&value) + 1);
|
|
}
|
|
|
|
iterator insert(iterator position, const_iterator first,
|
|
const_iterator last) {
|
|
size_t count = last - first;
|
|
if (size_ + count > kMaxSize) {
|
|
Err("vector::insert: out of space!");
|
|
return end();
|
|
}
|
|
|
|
std::copy(rbegin(), reverse_iterator(position),
|
|
reverse_iterator(end() + count));
|
|
size_ = size_ + count;
|
|
std::copy(first, last, position);
|
|
return position;
|
|
}
|
|
|
|
// methods for erasing elements
|
|
// note that all these methods might invalidate existing iterators
|
|
|
|
iterator erase(iterator it) {
|
|
return erase(it, it + 1);
|
|
}
|
|
|
|
iterator erase(iterator first, iterator last) {
|
|
size_t count = last - first;
|
|
std::copy(last, end(), first);
|
|
for (iterator it = end() - count, e = end(); it != e; ++it)
|
|
(*it).~ValueType();
|
|
size_ = size_ - count;
|
|
return first;
|
|
}
|
|
|
|
void clear() {
|
|
erase(begin(), end());
|
|
}
|
|
|
|
template<size_t kThatSize>
|
|
vector<ValueType, kMaxSize>& operator=(
|
|
const vector<ValueType, kThatSize>& that) {
|
|
clear();
|
|
insert(begin(), that.begin(), that.end());
|
|
return *this;
|
|
}
|
|
|
|
private:
|
|
ValueType buffer_[kMaxSize];
|
|
size_t size_;
|
|
};
|
|
|
|
} // namespace gestures
|
|
|
|
#endif // GESTURES_VECTOR_H__
|