/*
* Copyright (C) 2017 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef ANDROID_VINTF_MAP_VALUE_ITERATOR_H
#define ANDROID_VINTF_MAP_VALUE_ITERATOR_H
#include <iterator>
#include <map>
namespace android {
namespace vintf {
template<typename Map>
struct MapIterTypes {
using K = typename Map::key_type;
using V = typename Map::mapped_type;
// Iterator over all values of a Map
template<bool is_const>
struct IteratorImpl : public std::iterator <
std::bidirectional_iterator_tag, /* Category */
V,
ptrdiff_t, /* Distance */
typename std::conditional<is_const, const V *, V *>::type /* Pointer */,
typename std::conditional<is_const, const V &, V &>::type /* Reference */
>
{
using traits = std::iterator_traits<IteratorImpl>;
using ptr_type = typename traits::pointer;
using ref_type = typename traits::reference;
using diff_type = typename traits::difference_type;
using map_iter = typename std::conditional<is_const,
typename Map::const_iterator, typename Map::iterator>::type;
IteratorImpl(map_iter i) : mIter(i) {}
inline IteratorImpl &operator++() {
mIter++;
return *this;
}
inline IteratorImpl operator++(int) {
IteratorImpl i = *this;
mIter++;
return i;
}
inline IteratorImpl &operator--() {
mIter--;
return *this;
}
inline IteratorImpl operator--(int) {
IteratorImpl i = *this;
mIter--;
return i;
}
inline ref_type operator*() const { return mIter->second; }
inline ptr_type operator->() const { return &(mIter->second); }
inline bool operator==(const IteratorImpl &rhs) const { return mIter == rhs.mIter; }
inline bool operator!=(const IteratorImpl &rhs) const { return mIter != rhs.mIter; }
private:
map_iter mIter;
};
using ValueIterator = IteratorImpl<false>;
using ConstValueIterator = IteratorImpl<true>;
template<bool is_const>
struct IterableImpl {
using map_ref = typename std::conditional<is_const, const Map &, Map &>::type;
IterableImpl(map_ref map) : mMap(map) {}
IteratorImpl<is_const> begin() const {
return IteratorImpl<is_const>(mMap.begin());
}
IteratorImpl<is_const> end() const {
return IteratorImpl<is_const>(mMap.end());
}
bool empty() const { return begin() == end(); }
private:
map_ref mMap;
};
template <bool is_const>
struct RangeImpl {
using iter_type = typename std::conditional<is_const, typename Map::const_iterator,
typename Map::iterator>::type;
using range_type = std::pair<iter_type, iter_type>;
RangeImpl(range_type r) : mRange(r) {}
IteratorImpl<is_const> begin() const { return mRange.first; }
IteratorImpl<is_const> end() const { return mRange.second; }
bool empty() const { return begin() == end(); }
private:
range_type mRange;
};
using ValueIterable = IterableImpl<false>;
using ConstValueIterable = IterableImpl<true>;
};
template<typename K, typename V>
using ConstMapValueIterable = typename MapIterTypes<std::map<K, V>>::ConstValueIterable;
template<typename K, typename V>
using ConstMultiMapValueIterable = typename MapIterTypes<std::multimap<K, V>>::ConstValueIterable;
template <typename K, typename V>
using MapValueIterable = typename MapIterTypes<std::map<K, V>>::ValueIterable;
template <typename K, typename V>
using MultiMapValueIterable = typename MapIterTypes<std::multimap<K, V>>::ValueIterable;
template<typename K, typename V>
ConstMapValueIterable<K, V> iterateValues(const std::map<K, V> &map) {
return map;
}
template<typename K, typename V>
ConstMultiMapValueIterable<K, V> iterateValues(const std::multimap<K, V> &map) {
return map;
}
template <typename K, typename V>
MapValueIterable<K, V> iterateValues(std::map<K, V>& map) {
return map;
}
template <typename K, typename V>
MultiMapValueIterable<K, V> iterateValues(std::multimap<K, V>& map) {
return map;
}
template <typename K, typename V>
typename MapIterTypes<std::multimap<K, V>>::template RangeImpl<true> iterateValues(
const std::multimap<K, V>& map, const K& key) {
return map.equal_range(key);
}
} // namespace vintf
} // namespace android
#endif // ANDROID_VINTF_MAP_VALUE_ITERATOR_H