| // Copyright 2021 The Chromium Authors. All rights reserved. | 
 | // Use of this source code is governed by a BSD-style license that can be | 
 | // found in the LICENSE file. | 
 |  | 
 | #ifndef THIRD_PARTY_BASE_CONTAINERS_CONTAINS_H_ | 
 | #define THIRD_PARTY_BASE_CONTAINERS_CONTAINS_H_ | 
 |  | 
 | #include <algorithm> | 
 | #include <iterator> | 
 | #include <type_traits> | 
 |  | 
 | #include "third_party/base/template_util.h" | 
 |  | 
 | namespace pdfium { | 
 |  | 
 | namespace internal { | 
 |  | 
 | // Small helper to detect whether a given type has a nested `key_type` typedef. | 
 | // Used below to catch misuses of the API for associative containers. | 
 | template <typename T, typename SFINAE = void> | 
 | struct HasKeyType : std::false_type {}; | 
 |  | 
 | template <typename T> | 
 | struct HasKeyType<T, std::void_t<typename T::key_type>> : std::true_type {}; | 
 |  | 
 | // Utility type traits used for specializing base::Contains() below. | 
 | template <typename Container, typename Element, typename = void> | 
 | struct HasFindWithNpos : std::false_type {}; | 
 |  | 
 | template <typename Container, typename Element> | 
 | struct HasFindWithNpos< | 
 |     Container, | 
 |     Element, | 
 |     std::void_t<decltype(std::declval<const Container&>().find( | 
 |                              std::declval<const Element&>()) != | 
 |                          Container::npos)>> : std::true_type {}; | 
 |  | 
 | template <typename Container, typename Element, typename = void> | 
 | struct HasFindWithEnd : std::false_type {}; | 
 |  | 
 | template <typename Container, typename Element> | 
 | struct HasFindWithEnd< | 
 |     Container, | 
 |     Element, | 
 |     std::void_t<decltype(std::declval<const Container&>().find( | 
 |                              std::declval<const Element&>()) != | 
 |                          std::declval<const Container&>().end())>> | 
 |     : std::true_type {}; | 
 |  | 
 | template <typename Container, typename Element, typename = void> | 
 | struct HasContains : std::false_type {}; | 
 |  | 
 | template <typename Container, typename Element> | 
 | struct HasContains< | 
 |     Container, | 
 |     Element, | 
 |     std::void_t<decltype(std::declval<const Container&>().contains( | 
 |         std::declval<const Element&>()))>> : std::true_type {}; | 
 |  | 
 | }  // namespace internal | 
 |  | 
 | // General purpose implementation to check if |container| contains |value|. | 
 | template <typename Container, | 
 |           typename Value, | 
 |           std::enable_if_t< | 
 |               !internal::HasFindWithNpos<Container, Value>::value && | 
 |               !internal::HasFindWithEnd<Container, Value>::value && | 
 |               !internal::HasContains<Container, Value>::value>* = nullptr> | 
 | bool Contains(const Container& container, const Value& value) { | 
 |   static_assert( | 
 |       !internal::HasKeyType<Container>::value, | 
 |       "Error: About to perform linear search on an associative container. " | 
 |       "Either use a more generic comparator (e.g. std::less<>) or, if a linear " | 
 |       "search is desired, provide an explicit projection parameter."); | 
 |   using std::begin; | 
 |   using std::end; | 
 |   return std::find(begin(container), end(container), value) != end(container); | 
 | } | 
 |  | 
 | // Specialized Contains() implementation for when |container| has a find() | 
 | // member function and a static npos member, but no contains() member function. | 
 | template <typename Container, | 
 |           typename Value, | 
 |           std::enable_if_t<internal::HasFindWithNpos<Container, Value>::value && | 
 |                            !internal::HasContains<Container, Value>::value>* = | 
 |               nullptr> | 
 | bool Contains(const Container& container, const Value& value) { | 
 |   return container.find(value) != Container::npos; | 
 | } | 
 |  | 
 | // Specialized Contains() implementation for when |container| has a find() | 
 | // and end() member function, but no contains() member function. | 
 | template <typename Container, | 
 |           typename Value, | 
 |           std::enable_if_t<internal::HasFindWithEnd<Container, Value>::value && | 
 |                            !internal::HasContains<Container, Value>::value>* = | 
 |               nullptr> | 
 | bool Contains(const Container& container, const Value& value) { | 
 |   return container.find(value) != container.end(); | 
 | } | 
 |  | 
 | // Specialized Contains() implementation for when |container| has a contains() | 
 | // member function. | 
 | template < | 
 |     typename Container, | 
 |     typename Value, | 
 |     std::enable_if_t<internal::HasContains<Container, Value>::value>* = nullptr> | 
 | bool Contains(const Container& container, const Value& value) { | 
 |   return container.contains(value); | 
 | } | 
 |  | 
 | }  // namespace pdfium | 
 |  | 
 | #endif  // THIRD_PARTY_BASE_CONTAINERS_CONTAINS_H_ |