blob: 544dd21aefb9f7728737972e7d959788a0670f64 [file] [log] [blame]
// TODO: Insert description here. (generated by jdanis)
#ifndef KEYSTORE_INCLUDE_KEYSTORE_UTILS_H_
#define KEYSTORE_INCLUDE_KEYSTORE_UTILS_H_
#include <iterator>
#include <memory>
#include <vector>
namespace android {
namespace security {
/*
* This iterator abstracts from a collection of the form
* std::shared_ptr<COLLECTION_TYPE<std::unique_ptr<T>>>
* such that it is defined both for nulled outer pointer and
* nulled entries. If shared_ptr(nullptr) is passed in, the iterator behaves
* like the end iterator yielding an empty collection. Nulled
* entries are skipped so that the iterator is always dereferencable unless
* it is equal to end.
* The default constructor always yields an iterator equal to end.
* The same iterator invalidation rules apply as they do for the iterators
* of the corresponding collection.
*/
template <typename T, template <typename...> class Coll = std::vector>
class SharedNullableIterator {
public:
typedef Coll<std::unique_ptr<typename std::remove_const<T>::type>> CollectionType;
typedef std::shared_ptr<CollectionType> CollectionPtr;
SharedNullableIterator() {}
explicit SharedNullableIterator(const std::shared_ptr<CollectionType>& coll) : coll_(coll) {
init();
}
explicit SharedNullableIterator(std::shared_ptr<CollectionType>&& coll) : coll_(coll) {
init();
}
SharedNullableIterator(const SharedNullableIterator& other)
: coll_(other.coll_), cur_(other.cur_) {}
SharedNullableIterator(SharedNullableIterator&& other) noexcept
: coll_(std::move(other.coll_)), cur_(std::move(other.cur_)) {}
SharedNullableIterator& operator++() {
inc();
return *this;
}
SharedNullableIterator operator++(int) {
SharedNullableIterator retval(*this);
++(*this);
return retval;
}
T& operator*() const { return **cur_; }
T* operator->() const { return &**cur_; }
bool operator==(const SharedNullableIterator& other) const {
return cur_ == other.cur_ || (is_end() && other.is_end());
}
bool operator!=(const SharedNullableIterator& other) const { return !(*this == other); }
SharedNullableIterator& operator=(const SharedNullableIterator&) = default;
SharedNullableIterator& operator=(SharedNullableIterator&&) noexcept = default;
private:
inline bool is_end() const { return !coll_ || cur_ == coll_->end(); }
inline void inc() {
if (!is_end()) {
do {
++cur_;
// move forward to the next non null member or stay at end
} while (cur_ != coll_->end() && !(*cur_));
}
}
void init() {
if (coll_) {
// move forward to the first non null member
for (cur_ = coll_->begin(); cur_ != coll_->end() && !(*cur_); ++cur_) {
}
}
}
CollectionPtr coll_;
typename CollectionType::iterator cur_;
};
} // namespace security
} // namespace android
namespace std {
template <typename T, template <typename...> class COLL>
struct iterator_traits<android::security::SharedNullableIterator<T, COLL>> {
typedef T& reference;
typedef T value_type;
typedef T* pointer;
typedef forward_iterator_tag iterator_category;
};
}
#endif // KEYSTORE_INCLUDE_KEYSTORE_UTILS_H_