1 // TODO: Insert description here. (generated by jdanis)
2 
3 #ifndef KEYSTORE_INCLUDE_KEYSTORE_UTILS_H_
4 #define KEYSTORE_INCLUDE_KEYSTORE_UTILS_H_
5 
6 #include <iterator>
7 #include <memory>
8 #include <vector>
9 
10 namespace android {
11 namespace security {
12 
13 /*
14  * This iterator abstracts from a collection of the form
15  * std::shared_ptr<COLLECTION_TYPE<std::unique_ptr<T>>>
16  * such that it is defined both for nulled outer pointer and
17  * nulled entries. If shared_ptr(nullptr) is passed in, the iterator behaves
18  * like the end iterator yielding an empty collection. Nulled
19  * entries are skipped so that the iterator is always dereferencable unless
20  * it is equal to end.
21  * The default constructor always yields an iterator equal to end.
22  * The same iterator invalidation rules apply as they do for the iterators
23  * of the corresponding collection.
24  */
25 template <typename T, template <typename...> class Coll = std::vector>
26 class SharedNullableIterator {
27   public:
28     typedef Coll<std::unique_ptr<typename std::remove_const<T>::type>> CollectionType;
29     typedef std::shared_ptr<CollectionType> CollectionPtr;
30 
SharedNullableIterator()31     SharedNullableIterator() {}
SharedNullableIterator(const std::shared_ptr<CollectionType> & coll)32     explicit SharedNullableIterator(const std::shared_ptr<CollectionType>& coll) : coll_(coll) {
33         init();
34     }
SharedNullableIterator(std::shared_ptr<CollectionType> && coll)35     explicit SharedNullableIterator(std::shared_ptr<CollectionType>&& coll) : coll_(coll) {
36         init();
37     }
38 
SharedNullableIterator(const SharedNullableIterator & other)39     SharedNullableIterator(const SharedNullableIterator& other)
40         : coll_(other.coll_), cur_(other.cur_) {}
SharedNullableIterator(SharedNullableIterator && other)41     SharedNullableIterator(SharedNullableIterator&& other) noexcept
42         : coll_(std::move(other.coll_)), cur_(std::move(other.cur_)) {}
43 
44     SharedNullableIterator& operator++() {
45         inc();
46         return *this;
47     }
48     SharedNullableIterator operator++(int) {
49         SharedNullableIterator retval(*this);
50         ++(*this);
51         return retval;
52     }
53     T& operator*() const { return **cur_; }
54 
55     T* operator->() const { return &**cur_; }
56 
57     bool operator==(const SharedNullableIterator& other) const {
58         return cur_ == other.cur_ || (is_end() && other.is_end());
59     }
60     bool operator!=(const SharedNullableIterator& other) const { return !(*this == other); }
61 
62     SharedNullableIterator& operator=(const SharedNullableIterator&) = default;
63     SharedNullableIterator& operator=(SharedNullableIterator&&) noexcept = default;
64 
65   private:
is_end()66     inline bool is_end() const { return !coll_ || cur_ == coll_->end(); }
inc()67     inline void inc() {
68         if (!is_end()) {
69             do {
70                 ++cur_;
71                 // move forward to the next non null member or stay at end
72             } while (cur_ != coll_->end() && !(*cur_));
73         }
74     }
init()75     void init() {
76         if (coll_) {
77             // move forward to the first non null member
78             for (cur_ = coll_->begin(); cur_ != coll_->end() && !(*cur_); ++cur_) {
79             }
80         }
81     }
82 
83     CollectionPtr coll_;
84     typename CollectionType::iterator cur_;
85 };
86 
87 }  // namespace security
88 }  // namespace android
89 
90 namespace std {
91 template <typename T, template <typename...> class COLL>
92 struct iterator_traits<android::security::SharedNullableIterator<T, COLL>> {
93     typedef T& reference;
94     typedef T value_type;
95     typedef T* pointer;
96     typedef forward_iterator_tag iterator_category;
97 };
98 }
99 
100 #endif  // KEYSTORE_INCLUDE_KEYSTORE_UTILS_H_
101