Replace MakeFakeUniquePtr() with MatchesUniquePtr()
Borrow MatchesUniquePtr() from Chromium, instead of maintaining a
separate class that does something similar.
Change-Id: Ifb107b4e4b10487a78cbd6fa48e0885289cd6ca5
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/131251
Reviewed-by: Tom Sepez <tsepez@chromium.org>
Commit-Queue: Lei Zhang <thestig@chromium.org>
diff --git a/core/fpdfapi/page/cpdf_pageobjectholder.cpp b/core/fpdfapi/page/cpdf_pageobjectholder.cpp
index d1249ce..ed17e5f 100644
--- a/core/fpdfapi/page/cpdf_pageobjectholder.cpp
+++ b/core/fpdfapi/page/cpdf_pageobjectholder.cpp
@@ -17,6 +17,7 @@
#include "core/fpdfapi/parser/cpdf_document.h"
#include "core/fxcrt/check.h"
#include "core/fxcrt/check_op.h"
+#include "core/fxcrt/containers/unique_ptr_adapters.h"
#include "core/fxcrt/fx_extension.h"
#include "core/fxcrt/stl_util.h"
@@ -190,8 +191,8 @@
std::unique_ptr<CPDF_PageObject> CPDF_PageObjectHolder::RemovePageObject(
CPDF_PageObject* pPageObj) {
- auto it =
- std::ranges::find(page_object_list_, fxcrt::MakeFakeUniquePtr(pPageObj));
+ auto it = std::ranges::find_if(page_object_list_,
+ pdfium::MatchesUniquePtr(pPageObj));
if (it == std::end(page_object_list_)) {
return nullptr;
}
diff --git a/core/fpdfdoc/cpdf_annotlist.cpp b/core/fpdfdoc/cpdf_annotlist.cpp
index 846fa97..0936b45 100644
--- a/core/fpdfdoc/cpdf_annotlist.cpp
+++ b/core/fpdfdoc/cpdf_annotlist.cpp
@@ -30,6 +30,7 @@
#include "core/fpdfdoc/cpdf_generateap.h"
#include "core/fpdfdoc/cpdf_interactiveform.h"
#include "core/fxcrt/check.h"
+#include "core/fxcrt/containers/unique_ptr_adapters.h"
namespace {
@@ -234,9 +235,7 @@
bool CPDF_AnnotList::Contains(const CPDF_Annot* pAnnot) const {
auto it = std::ranges::find_if(
- annot_list_, [pAnnot](const std::unique_ptr<CPDF_Annot>& annot) {
- return annot.get() == pAnnot;
- });
+ annot_list_, pdfium::MatchesUniquePtr(const_cast<CPDF_Annot*>(pAnnot)));
return it != annot_list_.end();
}
diff --git a/core/fxcrt/BUILD.gn b/core/fxcrt/BUILD.gn
index 37ad003..3a0612f 100644
--- a/core/fxcrt/BUILD.gn
+++ b/core/fxcrt/BUILD.gn
@@ -50,6 +50,7 @@
"component_export.h",
"containers/adapters.h",
"containers/contains.h",
+ "containers/unique_ptr_adapters.h",
"data_vector.h",
"debug/alias.cc",
"debug/alias.h",
diff --git a/core/fxcrt/containers/unique_ptr_adapters.h b/core/fxcrt/containers/unique_ptr_adapters.h
new file mode 100644
index 0000000..a63ab35
--- /dev/null
+++ b/core/fxcrt/containers/unique_ptr_adapters.h
@@ -0,0 +1,52 @@
+// Copyright 2025 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_CONTAINERS_UNIQUE_PTR_ADAPTERS_H_
+#define CORE_FXCRT_CONTAINERS_UNIQUE_PTR_ADAPTERS_H_
+
+#include <memory>
+
+#include "core/fxcrt/unowned_ptr.h"
+
+// 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.
+// - Deleted MatchesUniquePtr() and UniquePtrComparator.
+// - Switched from raw_ptr to UnownedPtr.
+
+namespace pdfium {
+
+// UniquePtrMatcher is useful for finding an element in a container of
+// unique_ptrs when you have the raw pointer.
+//
+// Example usage:
+// std::vector<std::unique_ptr<Foo>> vector;
+// Foo* element = ...
+// auto iter = std::ranges::find_if(vector, MatchesUniquePtr(element));
+//
+// Example of erasing from container:
+// EraseIf(v, MatchesUniquePtr(element));
+//
+template <class T, class Deleter = std::default_delete<T>>
+struct UniquePtrMatcher {
+ explicit UniquePtrMatcher(T* t) : t_(t) {}
+
+ bool operator()(const std::unique_ptr<T, Deleter>& o) {
+ return o.get() == t_;
+ }
+
+ private:
+ const UnownedPtr<T> t_;
+};
+
+template <class T, class Deleter = std::default_delete<T>>
+UniquePtrMatcher<T, Deleter> MatchesUniquePtr(T* t) {
+ return UniquePtrMatcher<T, Deleter>(t);
+}
+
+} // namespace pdfium
+
+#endif // CORE_FXCRT_CONTAINERS_UNIQUE_PTR_ADAPTERS_H_
diff --git a/core/fxcrt/stl_util.h b/core/fxcrt/stl_util.h
index f0ba040..1d2f9a5 100644
--- a/core/fxcrt/stl_util.h
+++ b/core/fxcrt/stl_util.h
@@ -7,7 +7,6 @@
#include <algorithm>
#include <iterator>
-#include <memory>
#include "core/fxcrt/check_op.h"
#include "core/fxcrt/compiler_specific.h"
@@ -15,21 +14,6 @@
namespace fxcrt {
-// Means of generating a key for searching STL collections of std::unique_ptr
-// that avoids the side effect of deleting the pointer.
-template <class T>
-class FakeUniquePtr : public std::unique_ptr<T> {
- public:
- using std::unique_ptr<T>::unique_ptr;
- ~FakeUniquePtr() { std::unique_ptr<T>::release(); }
-};
-
-// Type-deducing wrapper for FakeUniquePtr<T>.
-template <class T>
-FakeUniquePtr<T> MakeFakeUniquePtr(T* arg) {
- return FakeUniquePtr<T>(arg);
-}
-
// Convenience routine for "int-fected" code, so that the stl collection
// size_t size() method return values will be checked.
template <typename ResultType, typename Collection>
diff --git a/fpdfsdk/cpdfsdk_pageview.cpp b/fpdfsdk/cpdfsdk_pageview.cpp
index 8ad3862..ed343f1 100644
--- a/fpdfsdk/cpdfsdk_pageview.cpp
+++ b/fpdfsdk/cpdfsdk_pageview.cpp
@@ -17,8 +17,7 @@
#include "core/fpdfdoc/cpdf_interactiveform.h"
#include "core/fxcrt/autorestorer.h"
#include "core/fxcrt/check.h"
-#include "core/fxcrt/containers/contains.h"
-#include "core/fxcrt/stl_util.h"
+#include "core/fxcrt/containers/unique_ptr_adapters.h"
#include "fpdfsdk/cpdfsdk_annot.h"
#include "fpdfsdk/cpdfsdk_annotiteration.h"
#include "fpdfsdk/cpdfsdk_annotiterator.h"
@@ -181,8 +180,8 @@
form_fill_env_->KillFocusAnnot({});
}
if (pAnnot) {
- auto it = std::ranges::find(sdkannot_array_,
- fxcrt::MakeFakeUniquePtr(pAnnot.Get()));
+ auto it = std::ranges::find_if(sdkannot_array_,
+ pdfium::MatchesUniquePtr(pAnnot.Get()));
if (it != sdkannot_array_.end()) {
sdkannot_array_.erase(it);
}
@@ -647,7 +646,10 @@
}
bool CPDFSDK_PageView::IsValidSDKAnnot(const CPDFSDK_Annot* p) const {
- return p && pdfium::Contains(sdkannot_array_, fxcrt::MakeFakeUniquePtr(p));
+ return p && std::ranges::find_if(
+ sdkannot_array_,
+ pdfium::MatchesUniquePtr(const_cast<CPDFSDK_Annot*>(p))) !=
+ sdkannot_array_.end();
}
CPDFSDK_Annot* CPDFSDK_PageView::GetFocusAnnot() {
diff --git a/fpdfsdk/fpdf_annot.cpp b/fpdfsdk/fpdf_annot.cpp
index c0d1017..40c74d7 100644
--- a/fpdfsdk/fpdf_annot.cpp
+++ b/fpdfsdk/fpdf_annot.cpp
@@ -33,6 +33,7 @@
#include "core/fpdfdoc/cpdf_interactiveform.h"
#include "core/fxcrt/check.h"
#include "core/fxcrt/containers/contains.h"
+#include "core/fxcrt/containers/unique_ptr_adapters.h"
#include "core/fxcrt/fx_safe_types.h"
#include "core/fxcrt/fx_string_wrappers.h"
#include "core/fxcrt/numerics/safe_conversions.h"
@@ -529,7 +530,8 @@
// Check that the object is already in this annotation's object list.
CPDF_Form* pForm = pAnnot->GetForm();
- if (!pdfium::Contains(*pForm, fxcrt::MakeFakeUniquePtr(pObj))) {
+ if (std::ranges::find_if(*pForm, pdfium::MatchesUniquePtr(pObj)) ==
+ pForm->end()) {
return false;
}
@@ -615,7 +617,8 @@
// Note that an object that came from a different annotation must not be
// passed here, since an object cannot belong to more than one annotation.
CPDF_Form* pForm = pAnnot->GetForm();
- if (pdfium::Contains(*pForm, fxcrt::MakeFakeUniquePtr(pObj))) {
+ if (std::ranges::find_if(*pForm, pdfium::MatchesUniquePtr(pObj)) !=
+ pForm->end()) {
return false;
}
diff --git a/fpdfsdk/pwl/cpwl_wnd.cpp b/fpdfsdk/pwl/cpwl_wnd.cpp
index f6d3fc6..67b84d8 100644
--- a/fpdfsdk/pwl/cpwl_wnd.cpp
+++ b/fpdfsdk/pwl/cpwl_wnd.cpp
@@ -14,7 +14,7 @@
#include "core/fxcrt/check.h"
#include "core/fxcrt/check_op.h"
#include "core/fxcrt/containers/contains.h"
-#include "core/fxcrt/stl_util.h"
+#include "core/fxcrt/containers/unique_ptr_adapters.h"
#include "core/fxge/cfx_renderdevice.h"
#include "fpdfsdk/pwl/cpwl_scroll_bar.h"
#include "public/fpdf_fwlevent.h"
@@ -431,7 +431,7 @@
void CPWL_Wnd::RemoveChild(CPWL_Wnd* pWnd) {
DCHECK_EQ(pWnd->parent_, this);
- auto it = std::ranges::find(children_, MakeFakeUniquePtr(pWnd));
+ auto it = std::ranges::find_if(children_, pdfium::MatchesUniquePtr(pWnd));
if (it == children_.end()) {
return;
}
diff --git a/fxjs/cjs_app.cpp b/fxjs/cjs_app.cpp
index 538bca4..e38e465 100644
--- a/fxjs/cjs_app.cpp
+++ b/fxjs/cjs_app.cpp
@@ -11,9 +11,9 @@
#include <algorithm>
#include <utility>
+#include "core/fxcrt/containers/unique_ptr_adapters.h"
#include "core/fxcrt/fixed_size_data_vector.h"
#include "core/fxcrt/span.h"
-#include "core/fxcrt/stl_util.h"
#include "fpdfsdk/cpdfsdk_formfillenvironment.h"
#include "fpdfsdk/cpdfsdk_interactiveform.h"
#include "fxjs/cjs_document.h"
@@ -419,7 +419,11 @@
}
void CJS_App::CancelProc(GlobalTimer* pTimer) {
- timers_.erase(fxcrt::MakeFakeUniquePtr(pTimer));
+ auto it = std::ranges::find_if(timers_, pdfium::MatchesUniquePtr(pTimer));
+ // Do this as a separate step, instead of using std::erase_if(), to avoid
+ // `pTimer` dangling. It would get deleted before MatchesUniquePtr goes out of
+ // scope.
+ timers_.erase(it);
}
void CJS_App::RunJsScript(CJS_Runtime* pRuntime, const WideString& wsScript) {
diff --git a/xfa/fwl/cfwl_listbox.cpp b/xfa/fwl/cfwl_listbox.cpp
index 74ae478..eb91d3e 100644
--- a/xfa/fwl/cfwl_listbox.cpp
+++ b/xfa/fwl/cfwl_listbox.cpp
@@ -10,6 +10,7 @@
#include <memory>
#include <utility>
+#include "core/fxcrt/containers/unique_ptr_adapters.h"
#include "core/fxcrt/numerics/safe_conversions.h"
#include "core/fxcrt/stl_util.h"
#include "v8/include/cppgc/visitor.h"
@@ -893,10 +894,7 @@
}
int32_t CFWL_ListBox::GetItemIndex(CFWL_Widget* pWidget, Item* pItem) {
- auto it = std::ranges::find_if(
- item_array_, [pItem](const std::unique_ptr<Item>& candidate) {
- return candidate.get() == pItem;
- });
+ auto it = std::ranges::find_if(item_array_, pdfium::MatchesUniquePtr(pItem));
return it != item_array_.end()
? checked_cast<int32_t>(it - item_array_.begin())
: -1;