• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2021 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #ifndef THIRD_PARTY_BASE_CONTAINERS_CONTAINS_H_
6 #define THIRD_PARTY_BASE_CONTAINERS_CONTAINS_H_
7 
8 #include <algorithm>
9 #include <iterator>
10 #include <type_traits>
11 
12 #include "third_party/base/template_util.h"
13 
14 namespace pdfium {
15 
16 namespace internal {
17 
18 // Small helper to detect whether a given type has a nested `key_type` typedef.
19 // Used below to catch misuses of the API for associative containers.
20 template <typename T, typename SFINAE = void>
21 struct HasKeyType : std::false_type {};
22 
23 template <typename T>
24 struct HasKeyType<T, std::void_t<typename T::key_type>> : std::true_type {};
25 
26 // Utility type traits used for specializing base::Contains() below.
27 template <typename Container, typename Element, typename = void>
28 struct HasFindWithNpos : std::false_type {};
29 
30 template <typename Container, typename Element>
31 struct HasFindWithNpos<
32     Container,
33     Element,
34     std::void_t<decltype(std::declval<const Container&>().find(
35                              std::declval<const Element&>()) !=
36                          Container::npos)>> : std::true_type {};
37 
38 template <typename Container, typename Element, typename = void>
39 struct HasFindWithEnd : std::false_type {};
40 
41 template <typename Container, typename Element>
42 struct HasFindWithEnd<
43     Container,
44     Element,
45     std::void_t<decltype(std::declval<const Container&>().find(
46                              std::declval<const Element&>()) !=
47                          std::declval<const Container&>().end())>>
48     : std::true_type {};
49 
50 template <typename Container, typename Element, typename = void>
51 struct HasContains : std::false_type {};
52 
53 template <typename Container, typename Element>
54 struct HasContains<
55     Container,
56     Element,
57     std::void_t<decltype(std::declval<const Container&>().contains(
58         std::declval<const Element&>()))>> : std::true_type {};
59 
60 }  // namespace internal
61 
62 // General purpose implementation to check if |container| contains |value|.
63 template <typename Container,
64           typename Value,
65           std::enable_if_t<
66               !internal::HasFindWithNpos<Container, Value>::value &&
67               !internal::HasFindWithEnd<Container, Value>::value &&
68               !internal::HasContains<Container, Value>::value>* = nullptr>
69 bool Contains(const Container& container, const Value& value) {
70   static_assert(
71       !internal::HasKeyType<Container>::value,
72       "Error: About to perform linear search on an associative container. "
73       "Either use a more generic comparator (e.g. std::less<>) or, if a linear "
74       "search is desired, provide an explicit projection parameter.");
75   using std::begin;
76   using std::end;
77   return std::find(begin(container), end(container), value) != end(container);
78 }
79 
80 // Specialized Contains() implementation for when |container| has a find()
81 // member function and a static npos member, but no contains() member function.
82 template <typename Container,
83           typename Value,
84           std::enable_if_t<internal::HasFindWithNpos<Container, Value>::value &&
85                            !internal::HasContains<Container, Value>::value>* =
86               nullptr>
87 bool Contains(const Container& container, const Value& value) {
88   return container.find(value) != Container::npos;
89 }
90 
91 // Specialized Contains() implementation for when |container| has a find()
92 // and end() member function, but no contains() member function.
93 template <typename Container,
94           typename Value,
95           std::enable_if_t<internal::HasFindWithEnd<Container, Value>::value &&
96                            !internal::HasContains<Container, Value>::value>* =
97               nullptr>
98 bool Contains(const Container& container, const Value& value) {
99   return container.find(value) != container.end();
100 }
101 
102 // Specialized Contains() implementation for when |container| has a contains()
103 // member function.
104 template <
105     typename Container,
106     typename Value,
107     std::enable_if_t<internal::HasContains<Container, Value>::value>* = nullptr>
108 bool Contains(const Container& container, const Value& value) {
109   return container.contains(value);
110 }
111 
112 }  // namespace pdfium
113 
114 #endif  // THIRD_PARTY_BASE_CONTAINERS_CONTAINS_H_
115