1 /*
2 * Copyright (C) 2017 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17
18 #ifndef ANDROID_VINTF_MAP_VALUE_ITERATOR_H
19 #define ANDROID_VINTF_MAP_VALUE_ITERATOR_H
20
21 #include <iterator>
22 #include <map>
23
24 namespace android {
25 namespace vintf {
26
27 template<typename Map>
28 struct MapIterTypes {
29 using K = typename Map::key_type;
30 using V = typename Map::mapped_type;
31
32 // Iterator over all values of a Map
33 template<bool is_const>
34 struct IteratorImpl : public std::iterator <
35 std::bidirectional_iterator_tag, /* Category */
36 V,
37 ptrdiff_t, /* Distance */
38 typename std::conditional<is_const, const V *, V *>::type /* Pointer */,
39 typename std::conditional<is_const, const V &, V &>::type /* Reference */
40 >
41 {
42 using traits = std::iterator_traits<IteratorImpl>;
43 using ptr_type = typename traits::pointer;
44 using ref_type = typename traits::reference;
45 using diff_type = typename traits::difference_type;
46
47 using map_iter = typename std::conditional<is_const,
48 typename Map::const_iterator, typename Map::iterator>::type;
49
IteratorImplMapIterTypes::IteratorImpl50 IteratorImpl(map_iter i) : mIter(i) {}
51
52 inline IteratorImpl &operator++() {
53 mIter++;
54 return *this;
55 }
56 inline IteratorImpl operator++(int) {
57 IteratorImpl i = *this;
58 mIter++;
59 return i;
60 }
61 inline IteratorImpl &operator--() {
62 mIter--;
63 return *this;
64 }
65 inline IteratorImpl operator--(int) {
66 IteratorImpl i = *this;
67 mIter--;
68 return i;
69 }
70 inline ref_type operator*() const { return mIter->second; }
71 inline ptr_type operator->() const { return &(mIter->second); }
72 inline bool operator==(const IteratorImpl &rhs) const { return mIter == rhs.mIter; }
73 inline bool operator!=(const IteratorImpl &rhs) const { return mIter != rhs.mIter; }
74
75 private:
76 map_iter mIter;
77 };
78
79 using ValueIterator = IteratorImpl<false>;
80 using ConstValueIterator = IteratorImpl<true>;
81
82 template<bool is_const>
83 struct IterableImpl {
84 using map_ref = typename std::conditional<is_const, const Map &, Map &>::type;
IterableImplMapIterTypes::IterableImpl85 IterableImpl(map_ref map) : mMap(map) {}
86
beginMapIterTypes::IterableImpl87 IteratorImpl<is_const> begin() const {
88 return IteratorImpl<is_const>(mMap.begin());
89 }
90
endMapIterTypes::IterableImpl91 IteratorImpl<is_const> end() const {
92 return IteratorImpl<is_const>(mMap.end());
93 }
94
emptyMapIterTypes::IterableImpl95 bool empty() const { return begin() == end(); }
96
97 private:
98 map_ref mMap;
99 };
100
101 template <bool is_const>
102 struct RangeImpl {
103 using iter_type = typename std::conditional<is_const, typename Map::const_iterator,
104 typename Map::iterator>::type;
105 using range_type = std::pair<iter_type, iter_type>;
RangeImplMapIterTypes::RangeImpl106 RangeImpl(range_type r) : mRange(r) {}
beginMapIterTypes::RangeImpl107 IteratorImpl<is_const> begin() const { return mRange.first; }
endMapIterTypes::RangeImpl108 IteratorImpl<is_const> end() const { return mRange.second; }
emptyMapIterTypes::RangeImpl109 bool empty() const { return begin() == end(); }
110
111 private:
112 range_type mRange;
113 };
114
115 using ValueIterable = IterableImpl<false>;
116 using ConstValueIterable = IterableImpl<true>;
117 };
118
119 template<typename K, typename V>
120 using ConstMapValueIterable = typename MapIterTypes<std::map<K, V>>::ConstValueIterable;
121 template<typename K, typename V>
122 using ConstMultiMapValueIterable = typename MapIterTypes<std::multimap<K, V>>::ConstValueIterable;
123 template <typename K, typename V>
124 using MapValueIterable = typename MapIterTypes<std::map<K, V>>::ValueIterable;
125 template <typename K, typename V>
126 using MultiMapValueIterable = typename MapIterTypes<std::multimap<K, V>>::ValueIterable;
127
128 template<typename K, typename V>
iterateValues(const std::map<K,V> & map)129 ConstMapValueIterable<K, V> iterateValues(const std::map<K, V> &map) {
130 return map;
131 }
132 template<typename K, typename V>
iterateValues(const std::multimap<K,V> & map)133 ConstMultiMapValueIterable<K, V> iterateValues(const std::multimap<K, V> &map) {
134 return map;
135 }
136 template <typename K, typename V>
iterateValues(std::map<K,V> & map)137 MapValueIterable<K, V> iterateValues(std::map<K, V>& map) {
138 return map;
139 }
140 template <typename K, typename V>
iterateValues(std::multimap<K,V> & map)141 MultiMapValueIterable<K, V> iterateValues(std::multimap<K, V>& map) {
142 return map;
143 }
144
145 template <typename K, typename V>
iterateValues(const std::multimap<K,V> & map,const K & key)146 typename MapIterTypes<std::multimap<K, V>>::template RangeImpl<true> iterateValues(
147 const std::multimap<K, V>& map, const K& key) {
148 return map.equal_range(key);
149 }
150
151 } // namespace vintf
152 } // namespace android
153
154 #endif // ANDROID_VINTF_MAP_VALUE_ITERATOR_H
155