118f27ade48405475ed610ee0067faa773211d598Janis Danisevskis// TODO: Insert description here. (generated by jdanis)
218f27ade48405475ed610ee0067faa773211d598Janis Danisevskis
318f27ade48405475ed610ee0067faa773211d598Janis Danisevskis#ifndef KEYSTORE_INCLUDE_KEYSTORE_UTILS_H_
418f27ade48405475ed610ee0067faa773211d598Janis Danisevskis#define KEYSTORE_INCLUDE_KEYSTORE_UTILS_H_
518f27ade48405475ed610ee0067faa773211d598Janis Danisevskis
618f27ade48405475ed610ee0067faa773211d598Janis Danisevskis#include <iterator>
718f27ade48405475ed610ee0067faa773211d598Janis Danisevskis#include <memory>
818f27ade48405475ed610ee0067faa773211d598Janis Danisevskis#include <vector>
918f27ade48405475ed610ee0067faa773211d598Janis Danisevskis
1018f27ade48405475ed610ee0067faa773211d598Janis Danisevskisnamespace android {
1118f27ade48405475ed610ee0067faa773211d598Janis Danisevskisnamespace security {
1218f27ade48405475ed610ee0067faa773211d598Janis Danisevskis
1318f27ade48405475ed610ee0067faa773211d598Janis Danisevskis/*
1418f27ade48405475ed610ee0067faa773211d598Janis Danisevskis * This iterator abstracts from a collection of the form
1518f27ade48405475ed610ee0067faa773211d598Janis Danisevskis * std::shared_ptr<COLLECTION_TYPE<std::unique_ptr<T>>>
1618f27ade48405475ed610ee0067faa773211d598Janis Danisevskis * such that it is defined both for nulled outer pointer and
1718f27ade48405475ed610ee0067faa773211d598Janis Danisevskis * nulled entries. If shared_ptr(nullptr) is passed in, the iterator behaves
1818f27ade48405475ed610ee0067faa773211d598Janis Danisevskis * like the end iterator yielding an empty collection. Nulled
1918f27ade48405475ed610ee0067faa773211d598Janis Danisevskis * entries are skipped so that the iterator is always dereferencable unless
2018f27ade48405475ed610ee0067faa773211d598Janis Danisevskis * it is equal to end.
2118f27ade48405475ed610ee0067faa773211d598Janis Danisevskis * The default constructor always yields an iterator equal to end.
2218f27ade48405475ed610ee0067faa773211d598Janis Danisevskis * The same iterator invalidation rules apply as they do for the iterators
2318f27ade48405475ed610ee0067faa773211d598Janis Danisevskis * of the corresponding collection.
2418f27ade48405475ed610ee0067faa773211d598Janis Danisevskis */
2518f27ade48405475ed610ee0067faa773211d598Janis Danisevskistemplate <typename T, template <typename...> class Coll = std::vector>
2618f27ade48405475ed610ee0067faa773211d598Janis Danisevskisclass SharedNullableIterator {
2718f27ade48405475ed610ee0067faa773211d598Janis Danisevskis  public:
2818f27ade48405475ed610ee0067faa773211d598Janis Danisevskis    typedef Coll<std::unique_ptr<typename std::remove_const<T>::type>> CollectionType;
2918f27ade48405475ed610ee0067faa773211d598Janis Danisevskis    typedef std::shared_ptr<CollectionType> CollectionPtr;
3018f27ade48405475ed610ee0067faa773211d598Janis Danisevskis
3118f27ade48405475ed610ee0067faa773211d598Janis Danisevskis    SharedNullableIterator() {}
3218f27ade48405475ed610ee0067faa773211d598Janis Danisevskis    SharedNullableIterator(const std::shared_ptr<CollectionType>& coll) : coll_(coll) { init(); }
3318f27ade48405475ed610ee0067faa773211d598Janis Danisevskis    SharedNullableIterator(std::shared_ptr<CollectionType>&& coll) : coll_(coll) { init(); }
3418f27ade48405475ed610ee0067faa773211d598Janis Danisevskis
3518f27ade48405475ed610ee0067faa773211d598Janis Danisevskis    SharedNullableIterator(const SharedNullableIterator& other)
3618f27ade48405475ed610ee0067faa773211d598Janis Danisevskis        : coll_(other.coll_), cur_(other.cur_) {}
3718f27ade48405475ed610ee0067faa773211d598Janis Danisevskis    SharedNullableIterator(SharedNullableIterator&& other)
3818f27ade48405475ed610ee0067faa773211d598Janis Danisevskis        : coll_(std::move(other.coll_)), cur_(std::move(other.cur_)) {}
3918f27ade48405475ed610ee0067faa773211d598Janis Danisevskis
4018f27ade48405475ed610ee0067faa773211d598Janis Danisevskis    SharedNullableIterator& operator++() {
4118f27ade48405475ed610ee0067faa773211d598Janis Danisevskis        inc();
4218f27ade48405475ed610ee0067faa773211d598Janis Danisevskis        return *this;
4318f27ade48405475ed610ee0067faa773211d598Janis Danisevskis    }
4418f27ade48405475ed610ee0067faa773211d598Janis Danisevskis    SharedNullableIterator operator++(int) {
4518f27ade48405475ed610ee0067faa773211d598Janis Danisevskis        SharedNullableIterator retval(*this);
4618f27ade48405475ed610ee0067faa773211d598Janis Danisevskis        ++(*this);
4718f27ade48405475ed610ee0067faa773211d598Janis Danisevskis        return retval;
4818f27ade48405475ed610ee0067faa773211d598Janis Danisevskis    }
4918f27ade48405475ed610ee0067faa773211d598Janis Danisevskis    T& operator*() const { return **cur_; }
5018f27ade48405475ed610ee0067faa773211d598Janis Danisevskis
5118f27ade48405475ed610ee0067faa773211d598Janis Danisevskis    T* operator->() const { return &**cur_; }
5218f27ade48405475ed610ee0067faa773211d598Janis Danisevskis
5318f27ade48405475ed610ee0067faa773211d598Janis Danisevskis    bool operator==(const SharedNullableIterator& other) const {
5418f27ade48405475ed610ee0067faa773211d598Janis Danisevskis        return cur_ == other.cur_ || (is_end() && other.is_end());
5518f27ade48405475ed610ee0067faa773211d598Janis Danisevskis    }
5618f27ade48405475ed610ee0067faa773211d598Janis Danisevskis    bool operator!=(const SharedNullableIterator& other) const { return !(*this == other); }
5718f27ade48405475ed610ee0067faa773211d598Janis Danisevskis
5818f27ade48405475ed610ee0067faa773211d598Janis Danisevskis    SharedNullableIterator& operator=(const SharedNullableIterator&) = default;
5918f27ade48405475ed610ee0067faa773211d598Janis Danisevskis    SharedNullableIterator& operator=(SharedNullableIterator&&) = default;
6018f27ade48405475ed610ee0067faa773211d598Janis Danisevskis
6118f27ade48405475ed610ee0067faa773211d598Janis Danisevskis  private:
6218f27ade48405475ed610ee0067faa773211d598Janis Danisevskis    inline bool is_end() const { return !coll_ || cur_ == coll_->end(); }
6318f27ade48405475ed610ee0067faa773211d598Janis Danisevskis    inline void inc() {
6418f27ade48405475ed610ee0067faa773211d598Janis Danisevskis        if (!is_end()) {
6518f27ade48405475ed610ee0067faa773211d598Janis Danisevskis            do {
6618f27ade48405475ed610ee0067faa773211d598Janis Danisevskis                ++cur_;
6718f27ade48405475ed610ee0067faa773211d598Janis Danisevskis                // move forward to the next non null member or stay at end
6818f27ade48405475ed610ee0067faa773211d598Janis Danisevskis            } while (cur_ != coll_->end() && !(*cur_));
6918f27ade48405475ed610ee0067faa773211d598Janis Danisevskis        }
7018f27ade48405475ed610ee0067faa773211d598Janis Danisevskis    }
7118f27ade48405475ed610ee0067faa773211d598Janis Danisevskis    void init() {
7218f27ade48405475ed610ee0067faa773211d598Janis Danisevskis        if (coll_) {
7318f27ade48405475ed610ee0067faa773211d598Janis Danisevskis            // move forward to the first non null member
7418f27ade48405475ed610ee0067faa773211d598Janis Danisevskis            for (cur_ = coll_->begin(); cur_ != coll_->end() && !(*cur_); ++cur_) {
7518f27ade48405475ed610ee0067faa773211d598Janis Danisevskis            }
7618f27ade48405475ed610ee0067faa773211d598Janis Danisevskis        }
7718f27ade48405475ed610ee0067faa773211d598Janis Danisevskis    }
7818f27ade48405475ed610ee0067faa773211d598Janis Danisevskis
7918f27ade48405475ed610ee0067faa773211d598Janis Danisevskis    CollectionPtr coll_;
8018f27ade48405475ed610ee0067faa773211d598Janis Danisevskis    typename CollectionType::iterator cur_;
8118f27ade48405475ed610ee0067faa773211d598Janis Danisevskis};
8218f27ade48405475ed610ee0067faa773211d598Janis Danisevskis
8318f27ade48405475ed610ee0067faa773211d598Janis Danisevskis}  // namespace security
8418f27ade48405475ed610ee0067faa773211d598Janis Danisevskis}  // namespace android
8518f27ade48405475ed610ee0067faa773211d598Janis Danisevskis
8618f27ade48405475ed610ee0067faa773211d598Janis Danisevskisnamespace std {
8718f27ade48405475ed610ee0067faa773211d598Janis Danisevskistemplate <typename T, template <typename...> class COLL>
8818f27ade48405475ed610ee0067faa773211d598Janis Danisevskisstruct iterator_traits<android::security::SharedNullableIterator<T, COLL>> {
8918f27ade48405475ed610ee0067faa773211d598Janis Danisevskis    typedef T& reference;
9018f27ade48405475ed610ee0067faa773211d598Janis Danisevskis    typedef T value_type;
9118f27ade48405475ed610ee0067faa773211d598Janis Danisevskis    typedef T* pointer;
9218f27ade48405475ed610ee0067faa773211d598Janis Danisevskis    typedef forward_iterator_tag iterator_category;
9318f27ade48405475ed610ee0067faa773211d598Janis Danisevskis};
9418f27ade48405475ed610ee0067faa773211d598Janis Danisevskis}
9518f27ade48405475ed610ee0067faa773211d598Janis Danisevskis
9618f27ade48405475ed610ee0067faa773211d598Janis Danisevskis#endif  // KEYSTORE_INCLUDE_KEYSTORE_UTILS_H_
97