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