Add a GetOrCreateDict() helper function.

Making sure one dictionary contains another dictionary is a fairly
common task. Add a helper to make that less tedious.

Change-Id: I386fb05f1af8216924dafc710fc9d04bcf050328
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/91550
Reviewed-by: Tom Sepez <tsepez@chromium.org>
Commit-Queue: Lei Zhang <thestig@chromium.org>
diff --git a/core/fpdfapi/edit/cpdf_pagecontentgenerator.cpp b/core/fpdfapi/edit/cpdf_pagecontentgenerator.cpp
index 6f694bf..5bb0ff0 100644
--- a/core/fpdfapi/edit/cpdf_pagecontentgenerator.cpp
+++ b/core/fpdfapi/edit/cpdf_pagecontentgenerator.cpp
@@ -185,10 +185,9 @@
         "Resources", m_pDocument.Get(),
         m_pObjHolder->GetResources()->GetObjNum());
   }
-  CPDF_Dictionary* pResList = m_pObjHolder->GetResources()->GetDictFor(bsType);
-  if (!pResList)
-    pResList = m_pObjHolder->GetResources()->SetNewFor<CPDF_Dictionary>(bsType);
 
+  CPDF_Dictionary* pResList =
+      GetOrCreateDict(m_pObjHolder->GetResources(), bsType);
   ByteString name;
   int idnum = 1;
   while (true) {
diff --git a/core/fpdfapi/parser/fpdf_parser_utility.cpp b/core/fpdfapi/parser/fpdf_parser_utility.cpp
index 6b01790..cccf189 100644
--- a/core/fpdfapi/parser/fpdf_parser_utility.cpp
+++ b/core/fpdfapi/parser/fpdf_parser_utility.cpp
@@ -93,6 +93,13 @@
   return pObj ? pObj->GetInteger() : 0;
 }
 
+CPDF_Dictionary* GetOrCreateDict(CPDF_Dictionary* dict, const ByteString& key) {
+  CPDF_Dictionary* result = dict->GetDictFor(key);
+  if (result)
+    return result;
+  return dict->SetNewFor<CPDF_Dictionary>(key);
+}
+
 ByteString PDF_NameDecode(ByteStringView orig) {
   size_t src_size = orig.GetLength();
   size_t out_index = 0;
diff --git a/core/fpdfapi/parser/fpdf_parser_utility.h b/core/fpdfapi/parser/fpdf_parser_utility.h
index fbe87bd..2752610 100644
--- a/core/fpdfapi/parser/fpdf_parser_utility.h
+++ b/core/fpdfapi/parser/fpdf_parser_utility.h
@@ -47,6 +47,8 @@
 
 int32_t GetDirectInteger(const CPDF_Dictionary* pDict, const ByteString& key);
 
+CPDF_Dictionary* GetOrCreateDict(CPDF_Dictionary* dict, const ByteString& key);
+
 ByteString PDF_NameDecode(ByteStringView orig);
 ByteString PDF_NameEncode(const ByteString& orig);
 
diff --git a/core/fpdfdoc/cpdf_bafontmap.cpp b/core/fpdfdoc/cpdf_bafontmap.cpp
index db2f793..9813a75 100644
--- a/core/fpdfdoc/cpdf_bafontmap.cpp
+++ b/core/fpdfdoc/cpdf_bafontmap.cpp
@@ -278,9 +278,8 @@
   if (!pFont)
     return;
 
-  CPDF_Dictionary* pAPDict = m_pAnnotDict->GetDictFor(pdfium::annotation::kAP);
-  if (!pAPDict)
-    pAPDict = m_pAnnotDict->SetNewFor<CPDF_Dictionary>(pdfium::annotation::kAP);
+  CPDF_Dictionary* pAPDict =
+      GetOrCreateDict(m_pAnnotDict.Get(), pdfium::annotation::kAP);
 
   // to avoid checkbox and radiobutton
   if (ToDictionary(pAPDict->GetObjectFor(m_sAPType)))
@@ -300,9 +299,7 @@
     pStream->InitStream({}, std::move(pOwnedDict));
   }
 
-  CPDF_Dictionary* pStreamResList = pStreamDict->GetDictFor("Resources");
-  if (!pStreamResList)
-    pStreamResList = pStreamDict->SetNewFor<CPDF_Dictionary>("Resources");
+  CPDF_Dictionary* pStreamResList = GetOrCreateDict(pStreamDict, "Resources");
   CPDF_Dictionary* pStreamResFontList = pStreamResList->GetDictFor("Font");
   if (!pStreamResFontList) {
     pStreamResFontList = m_pDocument->NewIndirect<CPDF_Dictionary>();
diff --git a/core/fpdfdoc/cpdf_generateap.cpp b/core/fpdfdoc/cpdf_generateap.cpp
index ff876f4..dc97759 100644
--- a/core/fpdfdoc/cpdf_generateap.cpp
+++ b/core/fpdfdoc/cpdf_generateap.cpp
@@ -511,10 +511,8 @@
   CPDF_Stream* pNormalStream = pDoc->NewIndirect<CPDF_Stream>();
   pNormalStream->SetDataFromStringstream(psAppStream);
 
-  CPDF_Dictionary* pAPDict = pAnnotDict->GetDictFor(pdfium::annotation::kAP);
-  if (!pAPDict)
-    pAPDict = pAnnotDict->SetNewFor<CPDF_Dictionary>(pdfium::annotation::kAP);
-
+  CPDF_Dictionary* pAPDict =
+      GetOrCreateDict(pAnnotDict, pdfium::annotation::kAP);
   pAPDict->SetNewFor<CPDF_Reference>("N", pDoc, pNormalStream->GetObjNum());
 
   CPDF_Dictionary* pStreamDict = pNormalStream->GetDict();
@@ -1063,10 +1061,8 @@
                     rcBBox.right - fBorderWidth, rcBBox.top - fBorderWidth);
   rcBody.Normalize();
 
-  CPDF_Dictionary* pAPDict = pAnnotDict->GetDictFor(pdfium::annotation::kAP);
-  if (!pAPDict)
-    pAPDict = pAnnotDict->SetNewFor<CPDF_Dictionary>(pdfium::annotation::kAP);
-
+  CPDF_Dictionary* pAPDict =
+      GetOrCreateDict(pAnnotDict, pdfium::annotation::kAP);
   CPDF_Stream* pNormalStream = pAPDict->GetStreamFor("N");
   if (!pNormalStream) {
     pNormalStream = pDoc->NewIndirect<CPDF_Stream>();
diff --git a/core/fpdfdoc/cpdf_interactiveform.cpp b/core/fpdfdoc/cpdf_interactiveform.cpp
index 9c2fcd1..355b056 100644
--- a/core/fpdfdoc/cpdf_interactiveform.cpp
+++ b/core/fpdfdoc/cpdf_interactiveform.cpp
@@ -247,13 +247,8 @@
     return;
   }
 
-  CPDF_Dictionary* pDR = pFormDict->GetDictFor("DR");
-  if (!pDR)
-    pDR = pFormDict->SetNewFor<CPDF_Dictionary>("DR");
-
-  CPDF_Dictionary* pFonts = pDR->GetDictFor("Font");
-  if (!pFonts)
-    pFonts = pDR->SetNewFor<CPDF_Dictionary>("Font");
+  CPDF_Dictionary* pDR = GetOrCreateDict(pFormDict, "DR");
+  CPDF_Dictionary* pFonts = GetOrCreateDict(pDR, "Font");
 
   if (csNameTag->IsEmpty())
     *csNameTag = pFont->GetBaseFontName();
diff --git a/fpdfsdk/cpdfsdk_appstream.cpp b/fpdfsdk/cpdfsdk_appstream.cpp
index 027cb1f..2edbc21 100644
--- a/fpdfsdk/cpdfsdk_appstream.cpp
+++ b/fpdfsdk/cpdfsdk_appstream.cpp
@@ -23,6 +23,7 @@
 #include "core/fpdfapi/parser/cpdf_stream.h"
 #include "core/fpdfapi/parser/cpdf_string.h"
 #include "core/fpdfapi/parser/fpdf_parser_decode.h"
+#include "core/fpdfapi/parser/fpdf_parser_utility.h"
 #include "core/fpdfdoc/cpdf_bafontmap.h"
 #include "core/fpdfdoc/cpdf_formcontrol.h"
 #include "core/fpdfdoc/cpdf_icon.h"
@@ -1830,10 +1831,7 @@
   if (pImageDict)
     sImageAlias = pImageDict->GetStringFor("Name");
 
-  CPDF_Dictionary* pStreamResList = pStreamDict->GetDictFor("Resources");
-  if (!pStreamResList)
-    pStreamResList = pStreamDict->SetNewFor<CPDF_Dictionary>("Resources");
-
+  CPDF_Dictionary* pStreamResList = GetOrCreateDict(pStreamDict, "Resources");
   CPDF_Dictionary* pXObject =
       pStreamResList->SetNewFor<CPDF_Dictionary>("XObject");
   pXObject->SetNewFor<CPDF_Reference>(sImageAlias,
@@ -1850,11 +1848,7 @@
     pParentDict = dict_.Get();
     key = sAPType;
   } else {
-    CPDF_Dictionary* pAPTypeDict = dict_->GetDictFor(sAPType);
-    if (!pAPTypeDict)
-      pAPTypeDict = dict_->SetNewFor<CPDF_Dictionary>(sAPType);
-
-    pParentDict = pAPTypeDict;
+    pParentDict = GetOrCreateDict(dict_.Get(), sAPType);
     key = sAPState;
   }
 
diff --git a/fpdfsdk/cpdfsdk_baannot.cpp b/fpdfsdk/cpdfsdk_baannot.cpp
index 0860908..d9cbe5a 100644
--- a/fpdfsdk/cpdfsdk_baannot.cpp
+++ b/fpdfsdk/cpdfsdk_baannot.cpp
@@ -17,6 +17,7 @@
 #include "core/fpdfapi/parser/cpdf_stream.h"
 #include "core/fpdfapi/parser/cpdf_string.h"
 #include "core/fpdfapi/parser/fpdf_parser_decode.h"
+#include "core/fpdfapi/parser/fpdf_parser_utility.h"
 #include "fpdfsdk/cpdfsdk_pageview.h"
 #include "third_party/base/check.h"
 
@@ -43,11 +44,7 @@
 }
 
 CPDF_Dictionary* CPDFSDK_BAAnnot::GetAPDict() const {
-  CPDF_Dictionary* pAPDict =
-      GetAnnotDict()->GetDictFor(pdfium::annotation::kAP);
-  if (pAPDict)
-    return pAPDict;
-  return GetAnnotDict()->SetNewFor<CPDF_Dictionary>(pdfium::annotation::kAP);
+  return GetOrCreateDict(GetAnnotDict(), pdfium::annotation::kAP);
 }
 
 CFX_FloatRect CPDFSDK_BAAnnot::GetRect() const {
@@ -105,9 +102,7 @@
   if (pBorder) {
     pBorder->SetNewAt<CPDF_Number>(2, nWidth);
   } else {
-    CPDF_Dictionary* pBSDict = GetAnnotDict()->GetDictFor("BS");
-    if (!pBSDict)
-      pBSDict = GetAnnotDict()->SetNewFor<CPDF_Dictionary>("BS");
+    CPDF_Dictionary* pBSDict = GetOrCreateDict(GetAnnotDict(), "BS");
     pBSDict->SetNewFor<CPDF_Number>("W", nWidth);
   }
 }
@@ -125,10 +120,7 @@
 }
 
 void CPDFSDK_BAAnnot::SetBorderStyle(BorderStyle nStyle) {
-  CPDF_Dictionary* pBSDict = GetAnnotDict()->GetDictFor("BS");
-  if (!pBSDict)
-    pBSDict = GetAnnotDict()->SetNewFor<CPDF_Dictionary>("BS");
-
+  CPDF_Dictionary* pBSDict = GetOrCreateDict(GetAnnotDict(), "BS");
   const char* name = nullptr;
   switch (nStyle) {
     case BorderStyle::kSolid:
diff --git a/fpdfsdk/fpdf_flatten.cpp b/fpdfsdk/fpdf_flatten.cpp
index 1efb188..0dcc58f 100644
--- a/fpdfsdk/fpdf_flatten.cpp
+++ b/fpdfsdk/fpdf_flatten.cpp
@@ -27,6 +27,7 @@
 #include "core/fpdfapi/parser/cpdf_reference.h"
 #include "core/fpdfapi/parser/cpdf_stream.h"
 #include "core/fpdfapi/parser/cpdf_stream_acc.h"
+#include "core/fpdfapi/parser/fpdf_parser_utility.h"
 #include "core/fpdfdoc/cpdf_annot.h"
 #include "core/fxcrt/fx_string_wrappers.h"
 #include "fpdfsdk/cpdfsdk_helpers.h"
@@ -294,18 +295,10 @@
   pPageDict->SetRectFor(pdfium::page_object::kCropBox, rcOriginalCB);
 
   CPDF_Dictionary* pRes =
-      pPageDict->GetDictFor(pdfium::page_object::kResources);
-  if (!pRes) {
-    pRes =
-        pPageDict->SetNewFor<CPDF_Dictionary>(pdfium::page_object::kResources);
-  }
-
+      GetOrCreateDict(pPageDict, pdfium::page_object::kResources);
   CPDF_Stream* pNewXObject = pDocument->NewIndirect<CPDF_Stream>(
       nullptr, 0, pDocument->New<CPDF_Dictionary>());
-
-  CPDF_Dictionary* pPageXObject = pRes->GetDictFor("XObject");
-  if (!pPageXObject)
-    pPageXObject = pRes->SetNewFor<CPDF_Dictionary>("XObject");
+  CPDF_Dictionary* pPageXObject = GetOrCreateDict(pRes, "XObject");
 
   ByteString key;
   if (!ObjectArray.empty()) {
@@ -397,10 +390,7 @@
       pObjDict->SetNewFor<CPDF_Name>("Subtype", "Form");
     }
 
-    CPDF_Dictionary* pXObject = pNewXORes->GetDictFor("XObject");
-    if (!pXObject)
-      pXObject = pNewXORes->SetNewFor<CPDF_Dictionary>("XObject");
-
+    CPDF_Dictionary* pXObject = GetOrCreateDict(pNewXORes, "XObject");
     ByteString sFormName = ByteString::Format("F%d", i);
     pXObject->SetNewFor<CPDF_Reference>(sFormName, pDocument,
                                         pObj->GetObjNum());
diff --git a/fpdfsdk/fpdf_ppo.cpp b/fpdfsdk/fpdf_ppo.cpp
index e80e44c..b307cac 100644
--- a/fpdfsdk/fpdf_ppo.cpp
+++ b/fpdfsdk/fpdf_ppo.cpp
@@ -29,6 +29,7 @@
 #include "core/fpdfapi/parser/cpdf_stream.h"
 #include "core/fpdfapi/parser/cpdf_stream_acc.h"
 #include "core/fpdfapi/parser/cpdf_string.h"
+#include "core/fpdfapi/parser/fpdf_parser_utility.h"
 #include "core/fpdfapi/render/cpdf_pagerendercache.h"
 #include "core/fxcrt/fx_safe_types.h"
 #include "core/fxcrt/fx_string_wrappers.h"
@@ -669,16 +670,8 @@
   DCHECK(pDestPageDict);
 
   CPDF_Dictionary* pRes =
-      pDestPageDict->GetDictFor(pdfium::page_object::kResources);
-  if (!pRes) {
-    pRes = pDestPageDict->SetNewFor<CPDF_Dictionary>(
-        pdfium::page_object::kResources);
-  }
-
-  CPDF_Dictionary* pPageXObject = pRes->GetDictFor("XObject");
-  if (!pPageXObject)
-    pPageXObject = pRes->SetNewFor<CPDF_Dictionary>("XObject");
-
+      GetOrCreateDict(pDestPageDict, pdfium::page_object::kResources);
+  CPDF_Dictionary* pPageXObject = GetOrCreateDict(pRes, "XObject");
   for (auto& it : m_XObjectNameToNumberMap)
     pPageXObject->SetNewFor<CPDF_Reference>(it.first, dest(), it.second);