blob: f3b7176b0921f34cc0f2c3874b6f84bda51cb62c [file] [log] [blame]
// 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"
#include "gestures/include/vector.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() {}
set(const set<Elt, kMaxSize>& that) {
*this = that;
}
template<size_t kThatSize>
set(const set<Elt, kThatSize>& that) {
*this = that;
}
size_t size() const { return vector_.size(); }
bool empty() const { return vector_.empty(); }
const_iterator begin() const { return vector_.begin(); }
const_iterator end() const { return vector_.end(); }
const_iterator find(const Elt& value) const { return vector_.find(value); }
// Non-const versions:
iterator begin() { return vector_.begin(); }
iterator end() { return vector_.end(); }
iterator find(const Elt& value) { return vector_.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);
it = vector_.insert(vector_.end(), value);
return std::make_pair(it, it != vector_.end());
}
// Returns number of elements removed (0 or 1).
// Unlike std::set, invalidates iterators.
size_t erase(const Elt& value) {
iterator it = vector_.find(value);
if (it == vector_.end())
return 0;
vector_.erase(it);
return 1;
}
void erase(iterator it) { vector_.erase(it); }
void clear() { vector_.clear(); }
template<size_t kThatSize>
set<Elt, kMaxSize>& operator=(const set<Elt, kThatSize>& that) {
vector_.clear();
vector_.insert(vector_.begin(), that.begin(), that.end());
return *this;
}
protected:
vector<Elt, kMaxSize> vector_;
};
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 all elements from |reduced| which are not in |required|
template<typename ReducedSet, typename RequiredSet>
inline void SetRemoveMissing(ReducedSet* reduced, const RequiredSet& required) {
typename ReducedSet::iterator it = reduced->begin();
while (it != reduced->end()) {
if (SetContainsValue(required, *it)) {
++it;
continue;
}
if (it == reduced->begin()) {
reduced->erase(it);
it = reduced->begin();
} else {
typename ReducedSet::iterator it_copy = it;
--it;
reduced->erase(it_copy);
++it;
}
}
}
// 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]);
}
// returns Difference = left - right.
template<typename LeftSet, typename RightSet>
LeftSet SetSubtract(const LeftSet& left, const RightSet& right) {
if (left.empty() || right.empty())
return left;
LeftSet ret;
for (typename LeftSet::const_iterator it = left.begin(), e = left.end();
it != e; ++it) {
if (!SetContainsValue(right, *it))
ret.insert(*it);
}
return ret;
}
} // namespace gestures
#endif // GESTURES_SET_H__