blob: d143f6a2333f8bd4b917c60254e0d3e8cbc54341 [file]
// Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef GESTURES_SET_H__
#define GESTURES_SET_H__
#include <algorithm>
#include "gestures/include/gestures.h"
#include "gestures/include/logging.h"
// This is a set class that doesn't call out to malloc/free. Many of the
// names were chosen to mirror std::set.
// A template parameter to this class is kMaxSize, which is the max number
// of elements that such a set can hold. Internally, it contains an array
// of Elt objects.
// Differences from std::set:
// - Many methods are unimplemented
// - insert()/erase() invalidate existing iterators
// - Currently, the Elt type should be a POD type or aggregate of PODs,
// since ctors/dtors aren't called propertly on Elt objects.
namespace gestures {
template<typename Elt, size_t kMaxSize>
class set {
public:
typedef Elt* iterator;
typedef const Elt* const_iterator;
set() : size_(0) {}
set(const set<Elt, kMaxSize>& that) {
*this = that;
}
template<size_t kThatSize>
set(const set<Elt, kThatSize>& that) {
*this = that;
}
const_iterator begin() const { return buffer_; }
const_iterator end() const {
const_iterator ret = &buffer_[size_];
return ret;
}
const_iterator find(const Elt& value) const {
for (size_t i = 0; i < size_; ++i)
if (buffer_[i] == value)
return &buffer_[i];
return end();
}
size_t size() const { return size_; }
bool empty() const { return size() == 0; }
// Non-const versions:
iterator begin() {
return const_cast<iterator>(
const_cast<const set<Elt, kMaxSize>*>(this)->begin());
}
iterator end() {
return const_cast<iterator>(
const_cast<const set<Elt, kMaxSize>*>(this)->end());
}
iterator find(const Elt& value) {
return const_cast<iterator>(
const_cast<const set<Elt, kMaxSize>*>(this)->find(value));
}
// Unlike std::set, invalidates iterators.
std::pair<iterator, bool> insert(const Elt& value) {
iterator it = find(value);
if (it != end())
return std::make_pair(it, false);
if (size_ == kMaxSize) {
Err("set::insert: out of space!");
return std::make_pair(end(), false);
}
iterator new_elt = &buffer_[size_];
new (new_elt) Elt(value);
++size_;
return std::make_pair(new_elt, true);
}
// Returns number of elements removed (0 or 1).
// Unlike std::set, invalidates iterators.
size_t erase(const Elt& value) {
iterator ptr = find(value);
if (ptr == end())
return 0;
erase(ptr);
return 1;
}
void erase(iterator it) {
std::copy(it + 1, end(), it);
(*(end() - 1)).~Elt();
--size_;
}
void clear() {
for (iterator it = begin(), e = end(); it != e; ++it)
(*it).~Elt();
size_ = 0;
}
template<size_t kThatSize>
set<Elt, kMaxSize>& operator=(const set<Elt, kThatSize>& that) {
if (that.size() > kMaxSize) {
// Uh oh, that won't fit into this
Err("set::operator=: out of space!");
return *this;
}
std::copy(that.begin(), that.end(), begin());
if (size_ > that.size())
for (iterator it = begin() + that.size(), e = end(); it != e; ++it)
(*it).~Elt();
size_ = that.size();
return *this;
}
private:
Elt buffer_[kMaxSize];
unsigned short size_;
};
template<typename Elt, size_t kLeftMaxSize, size_t kRightMaxSize>
inline bool operator==(const set<Elt, kLeftMaxSize>& left,
const set<Elt, kRightMaxSize>& right) {
if (left.size() != right.size())
return false;
for (typename set<Elt, kLeftMaxSize>::const_iterator left_it = left.begin(),
left_end = left.end(); left_it != left_end; ++left_it)
if (right.find(*left_it) == right.end())
return false;
return true;
}
template<typename Elt, size_t kLeftMaxSize, size_t kRightMaxSize>
inline bool operator!=(const set<Elt, kLeftMaxSize>& left,
const set<Elt, kRightMaxSize>& right) {
return !(left == right);
}
template<typename Set, typename Elt>
inline bool SetContainsValue(const Set& the_set,
const Elt& elt) {
return the_set.find(elt) != the_set.end();
}
// Removes any ids from the set that are not finger ids in hs.
template<size_t kSetSize>
void RemoveMissingIdsFromSet(set<short, kSetSize>* the_set,
const HardwareState& hs) {
short old_ids[the_set->size()];
size_t old_ids_len = 0;
for (typename set<short, kSetSize>::const_iterator it = the_set->begin();
it != the_set->end(); ++it)
if (!hs.GetFingerState(*it))
old_ids[old_ids_len++] = *it;
for (size_t i = 0; i < old_ids_len; i++)
the_set->erase(old_ids[i]);
}
} // namespace gestures
#endif // GESTURES_SET_H__