// Copyright 2016 The Android Open Source Project // // This software is licensed under the terms of the GNU General Public // License version 2, as published by the Free Software Foundation, and // may be copied, distributed, and modified under those terms. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. #pragma once #include "android/base/TypeTraits.h" #include #include #include #include #include #include // A set of convenience functions for map and set lookups. They allow a simpler // syntax, e.g. // if (auto val = find(map, "key")) { // // } // ... or // auto value = find(funcThatReturnsMap(), "other_key"); // if (!value) ... // // Note: these don't work for multimaps, as there's no single value // to return (and, more importantly, as those are completely useless). namespace android { namespace base { // Helper predicates that check if the template argument is a map / set / // a mutlikey collection of any kind. // These are used as a constraints for the lookup functions to get better error // messages if the arguments don't support the map interface. template using is_any_map = std::integral_constant< bool, is_template_instantiation_of::value || is_template_instantiation_of::value>; template using is_any_set = std::integral_constant< bool, is_template_instantiation_of::value || is_template_instantiation_of::value>; template using is_any_multikey = std::integral_constant< bool, is_template_instantiation_of::value || is_template_instantiation_of::value || is_template_instantiation_of::value || is_template_instantiation_of::value>; template >> const typename T::mapped_type* find(const T& map, const typename T::key_type& key) { const auto it = map.find(key); if (it == map.end()) { return nullptr; } return &it->second; } // Version that returns a modifiable value. template >> typename T::mapped_type* find(T& map, const typename T::key_type& key) { auto it = map.find(key); if (it == map.end()) { return nullptr; } return &it->second; } // Version with a default, returns a _copy_ because of the possible fallback // to a default - it might be destroyed after the call. template ::value && std::is_convertible::value>> typename T::mapped_type findOrDefault(const T& map, const typename T::key_type& key, U&& defaultVal = {}) { if (auto valPtr = find(map, key)) { return *valPtr; } return defaultVal; } // Version that finds the first of the values passed in |keys| in the order they // are passed. E.g., the following code finds '2' as the first value in |keys|: // set s = {1, 2, 3}; // auto val = findFirstOf(s, {2, 1}); // EXPECT_EQ(2, *val); template >> const typename T::mapped_type* findFirstOf( const T& map, std::initializer_list keys) { for (const auto& key : keys) { if (const auto valPtr = find(map, key)) { return valPtr; } } return nullptr; } template >> typename T::mapped_type* findFirstOf( T& map, std::initializer_list keys) { for (const auto& key : keys) { if (const auto valPtr = find(map, key)) { return valPtr; } } return nullptr; } // Version that finds first of the passed |key| values or returns the // |defaultVal| if none were found. template ::value && std::is_convertible::value>> typename T::mapped_type findFirstOfOrDefault( const T& map, std::initializer_list keys, U&& defaultVal) { if (const auto valPtr = findFirstOf(map, keys)) { return *valPtr; } return std::forward(defaultVal); } template ::value || is_any_set::value || is_any_multikey::value>> bool contains(const T& c, const typename T::key_type& key) { const auto it = c.find(key); return it != c.end(); } template ::value || is_any_set::value || is_any_multikey::value>> bool containsAnyOf(const T& c, std::initializer_list keys) { for (const auto& key : keys) { if (contains(c, key)) { return true; } } return false; } } // namespace base } // namespace android