Update pdfium::Contains() from Chromium Now that C++20 is available, sync core/fxcrt/containers/contains.h with Chromium's base//contains/contains.h at https://crrev.com/1414269, but with a cleaner set of #includes. Then delete template_util.h, and fix the build by using the Contains() overload that takes a projection. Change-Id: I27d7a7a54402e6a6edc3a8d9f7e3fdc5502f731e Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/131252 Commit-Queue: Lei Zhang <thestig@chromium.org> Reviewed-by: Tom Sepez <tsepez@chromium.org>
diff --git a/core/fxcrt/BUILD.gn b/core/fxcrt/BUILD.gn index 3a0612f..796a10a 100644 --- a/core/fxcrt/BUILD.gn +++ b/core/fxcrt/BUILD.gn
@@ -119,7 +119,6 @@ "string_template.cpp", "string_template.h", "string_view_template.h", - "template_util.h", "tree_node.h", "unowned_ptr.h", "utf16.h",
diff --git a/core/fxcrt/containers/contains.h b/core/fxcrt/containers/contains.h index e25f2f8..3175d49 100644 --- a/core/fxcrt/containers/contains.h +++ b/core/fxcrt/containers/contains.h
@@ -5,108 +5,57 @@ #ifndef CORE_FXCRT_CONTAINERS_CONTAINS_H_ #define CORE_FXCRT_CONTAINERS_CONTAINS_H_ -#include <algorithm> -#include <iterator> -#include <type_traits> +// This is Chromium's base/containers/unique_ptr_adapters.h, adapted to work +// with PDFium's codebase with the following modifications: +// +// - Updated include guards. +// - Replaced namespace base with namespace pdfium. +// - Replaced <type_traits> with <concepts>. -#include "core/fxcrt/template_util.h" +// Provides `Contains()`, a general purpose utility to check whether a container +// contains a value. This will probe whether a `contains` or `find` member +// function on `container` exists, and fall back to a generic linear search over +// `container`. + +#include <algorithm> +#include <concepts> +#include <ranges> +#include <utility> 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 pdfium::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); +// A general purpose utility to check whether `container` contains `value`. This +// will probe whether a `contains` or `find` member function on `container` +// exists, and fall back to a generic linear search over `container`. +template <typename Container, typename Value> +constexpr bool Contains(const Container& container, const Value& value) { + if constexpr (requires { + { container.contains(value) } -> std::same_as<bool>; + }) { + return container.contains(value); + } else if constexpr (requires { container.find(value) != Container::npos; }) { + return container.find(value) != Container::npos; + } else if constexpr (requires { container.find(value) != container.end(); }) { + return container.find(value) != container.end(); + } else { + static_assert( + !requires { typename Container::key_type; }, + "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."); + return std::ranges::find(container, value) != std::ranges::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); +// Overload that allows callers to provide an additional projection invocable. +// This projection will be applied to every element in `container` before +// comparing it with `value`. This will always perform a linear search. +template <typename Container, typename Value, typename Proj> +constexpr bool Contains(const Container& container, + const Value& value, + Proj proj) { + return std::ranges::find(container, value, std::move(proj)) != + std::ranges::end(container); } } // namespace pdfium
diff --git a/core/fxcrt/template_util.h b/core/fxcrt/template_util.h deleted file mode 100644 index a6abcb0..0000000 --- a/core/fxcrt/template_util.h +++ /dev/null
@@ -1,52 +0,0 @@ -// Copyright 2024 The PDFium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CORE_FXCRT_TEMPLATE_UTIL_H_ -#define CORE_FXCRT_TEMPLATE_UTIL_H_ - -#include <stddef.h> -#include <iosfwd> -#include <iterator> -#include <type_traits> -#include <utility> - -#include "build/build_config.h" - -namespace pdfium { - -template <class T> -struct is_non_const_reference : std::false_type {}; -template <class T> -struct is_non_const_reference<T&> : std::true_type {}; -template <class T> -struct is_non_const_reference<const T&> : std::false_type {}; - -namespace internal { - -// Uses expression SFINAE to detect whether using operator<< would work. -template <typename T, typename = void> -struct SupportsOstreamOperator : std::false_type {}; -template <typename T> -struct SupportsOstreamOperator<T, - decltype(void(std::declval<std::ostream&>() - << std::declval<T>()))> - : std::true_type {}; - -// Used to detech whether the given type is an iterator. This is normally used -// with std::enable_if to provide disambiguation for functions that take -// templatzed iterators as input. -template <typename T, typename = void> -struct is_iterator : std::false_type {}; - -template <typename T> -struct is_iterator< - T, - std::void_t<typename std::iterator_traits<T>::iterator_category>> - : std::true_type {}; - -} // namespace internal - -} // namespace pdfium - -#endif // CORE_FXCRT_TEMPLATE_UTIL_H_
diff --git a/fxjs/xfa/cfxjse_engine.cpp b/fxjs/xfa/cfxjse_engine.cpp index b1a589f..b1f9aac 100644 --- a/fxjs/xfa/cfxjse_engine.cpp +++ b/fxjs/xfa/cfxjse_engine.cpp
@@ -941,7 +941,9 @@ } void CFXJSE_Engine::AddNodesOfRunScript(CXFA_Node* pNode) { - if (script_node_array_ && !pdfium::Contains(*script_node_array_, pNode)) { + if (script_node_array_ && + !pdfium::Contains(*script_node_array_, pNode, + &cppgc::Persistent<CXFA_Node>::Get)) { script_node_array_->emplace_back(pNode); } }