Merget to XFA: Use std::map in CPDF_IndirectObjects

Review URL: https://codereview.chromium.org/1576113003 .
(cherry picked from commit fce548047a44c7015996874452f3e778bf64cad6)

TBR=thestig@chromium.org

Review URL: https://codereview.chromium.org/1579693004 .
diff --git a/core/include/fpdfapi/fpdf_objects.h b/core/include/fpdfapi/fpdf_objects.h
index 5e17685..80d978e 100644
--- a/core/include/fpdfapi/fpdf_objects.h
+++ b/core/include/fpdfapi/fpdf_objects.h
@@ -18,7 +18,7 @@
 class CPDF_CryptoHandler;
 class CPDF_Dictionary;
 class CPDF_Document;
-class CPDF_IndirectObjects;
+class CPDF_IndirectObjectHolder;
 class CPDF_Name;
 class CPDF_Null;
 class CPDF_Number;
@@ -54,7 +54,7 @@
 
   CPDF_Object* Clone(FX_BOOL bDirect = FALSE) const;
 
-  CPDF_Object* CloneRef(CPDF_IndirectObjects* pObjs) const;
+  CPDF_Object* CloneRef(CPDF_IndirectObjectHolder* pObjs) const;
 
   CPDF_Object* GetDirect() const;
 
@@ -128,7 +128,7 @@
   FX_DWORD m_ObjNum;
   FX_DWORD m_GenNum;
 
-  friend class CPDF_IndirectObjects;
+  friend class CPDF_IndirectObjectHolder;
   friend class CPDF_Parser;
   friend class CPDF_SyntaxParser;
 
@@ -295,15 +295,15 @@
 
   void SetAt(FX_DWORD index,
              CPDF_Object* pObj,
-             CPDF_IndirectObjects* pObjs = NULL);
+             CPDF_IndirectObjectHolder* pObjs = NULL);
 
   void InsertAt(FX_DWORD index,
                 CPDF_Object* pObj,
-                CPDF_IndirectObjects* pObjs = NULL);
+                CPDF_IndirectObjectHolder* pObjs = NULL);
 
   void RemoveAt(FX_DWORD index, int nCount = 1);
 
-  void Add(CPDF_Object* pObj, CPDF_IndirectObjects* pObjs = NULL);
+  void Add(CPDF_Object* pObj, CPDF_IndirectObjectHolder* pObjs = NULL);
 
   void AddNumber(FX_FLOAT f);
 
@@ -313,9 +313,9 @@
 
   void AddName(const CFX_ByteString& str);
 
-  void AddReference(CPDF_IndirectObjects* pDoc, FX_DWORD objnum);
+  void AddReference(CPDF_IndirectObjectHolder* pDoc, FX_DWORD objnum);
 
-  void AddReference(CPDF_IndirectObjects* pDoc, CPDF_Object* obj) {
+  void AddReference(CPDF_IndirectObjectHolder* pDoc, CPDF_Object* obj) {
     AddReference(pDoc, obj->GetObjNum());
   }
 
@@ -396,17 +396,17 @@
   void SetAtNumber(const CFX_ByteStringC& key, FX_FLOAT f);
 
   void SetAtReference(const CFX_ByteStringC& key,
-                      CPDF_IndirectObjects* pDoc,
+                      CPDF_IndirectObjectHolder* pDoc,
                       FX_DWORD objnum);
 
   void SetAtReference(const CFX_ByteStringC& key,
-                      CPDF_IndirectObjects* pDoc,
+                      CPDF_IndirectObjectHolder* pDoc,
                       CPDF_Object* obj) {
     SetAtReference(key, pDoc, obj->GetObjNum());
   }
 
   void AddReference(const CFX_ByteStringC& key,
-                    CPDF_IndirectObjects* pDoc,
+                    CPDF_IndirectObjectHolder* pDoc,
                     FX_DWORD objnum);
 
   void SetAtRect(const CFX_ByteStringC& key, const CFX_FloatRect& rect);
@@ -548,21 +548,21 @@
 
 class CPDF_Reference : public CPDF_Object {
  public:
-  CPDF_Reference(CPDF_IndirectObjects* pDoc, int objnum)
+  CPDF_Reference(CPDF_IndirectObjectHolder* pDoc, int objnum)
       : CPDF_Object(PDFOBJ_REFERENCE), m_pObjList(pDoc), m_RefObjNum(objnum) {}
 
-  CPDF_IndirectObjects* GetObjList() const { return m_pObjList; }
+  CPDF_IndirectObjectHolder* GetObjList() const { return m_pObjList; }
 
   FX_DWORD GetRefObjNum() const { return m_RefObjNum; }
 
-  void SetRef(CPDF_IndirectObjects* pDoc, FX_DWORD objnum);
+  void SetRef(CPDF_IndirectObjectHolder* pDoc, FX_DWORD objnum);
 
   FX_BOOL Identical(CPDF_Reference* pOther) const {
     return m_RefObjNum == pOther->m_RefObjNum;
   }
 
  protected:
-  CPDF_IndirectObjects* m_pObjList;
+  CPDF_IndirectObjectHolder* m_pObjList;
 
   FX_DWORD m_RefObjNum;
   friend class CPDF_Object;
@@ -574,40 +574,32 @@
   return obj ? obj->AsReference() : nullptr;
 }
 
-class CPDF_IndirectObjects {
+class CPDF_IndirectObjectHolder {
  public:
-  explicit CPDF_IndirectObjects(CPDF_Parser* pParser);
+  using iterator = std::map<FX_DWORD, CPDF_Object*>::iterator;
+  using const_iterator = std::map<FX_DWORD, CPDF_Object*>::const_iterator;
 
-  ~CPDF_IndirectObjects();
-
-  CPDF_Object* GetIndirectObject(FX_DWORD objnum, PARSE_CONTEXT* pContext);
+  explicit CPDF_IndirectObjectHolder(CPDF_Parser* pParser);
+  ~CPDF_IndirectObjectHolder();
 
   int GetIndirectType(FX_DWORD objnum);
-
+  CPDF_Object* GetIndirectObject(FX_DWORD objnum, PARSE_CONTEXT* pContext);
   FX_DWORD AddIndirectObject(CPDF_Object* pObj);
-
   void ReleaseIndirectObject(FX_DWORD objnum);
+
   // Takes ownership of |pObj|.
   FX_BOOL InsertIndirectObject(FX_DWORD objnum, CPDF_Object* pObj);
 
-  FX_DWORD GetLastObjNum() const;
-
-  FX_POSITION GetStartPosition() const {
-    return m_IndirectObjs.GetStartPosition();
-  }
-
-  void GetNextAssoc(FX_POSITION& rPos,
-                    FX_DWORD& objnum,
-                    CPDF_Object*& pObject) const {
-    m_IndirectObjs.GetNextAssoc(rPos, (void*&)objnum, (void*&)pObject);
-  }
+  FX_DWORD GetLastObjNum() const { return m_LastObjNum; }
+  iterator begin() { return m_IndirectObjs.begin(); }
+  const_iterator begin() const { return m_IndirectObjs.cbegin(); }
+  iterator end() { return m_IndirectObjs.end(); }
+  const_iterator end() const { return m_IndirectObjs.end(); }
 
  protected:
-  CFX_MapPtrToPtr m_IndirectObjs;
-
   CPDF_Parser* m_pParser;
-
   FX_DWORD m_LastObjNum;
+  std::map<FX_DWORD, CPDF_Object*> m_IndirectObjs;
 };
 
 #endif  // CORE_INCLUDE_FPDFAPI_FPDF_OBJECTS_H_
diff --git a/core/include/fpdfapi/fpdf_parser.h b/core/include/fpdfapi/fpdf_parser.h
index e1901eb..32c1982 100644
--- a/core/include/fpdfapi/fpdf_parser.h
+++ b/core/include/fpdfapi/fpdf_parser.h
@@ -64,7 +64,7 @@
 // Indexed by 8-bit char code, contains unicode code points.
 extern const FX_WORD PDFDocEncoding[256];
 
-class CPDF_Document : public CFX_PrivateData, public CPDF_IndirectObjects {
+class CPDF_Document : public CFX_PrivateData, public CPDF_IndirectObjectHolder {
  public:
   CPDF_Document();
   explicit CPDF_Document(CPDF_Parser* pParser);
@@ -243,13 +243,13 @@
 
   void RestorePos(FX_FILESIZE pos) { m_Pos = pos; }
 
-  CPDF_Object* GetObject(CPDF_IndirectObjects* pObjList,
+  CPDF_Object* GetObject(CPDF_IndirectObjectHolder* pObjList,
                          FX_DWORD objnum,
                          FX_DWORD gennum,
                          PARSE_CONTEXT* pContext,
                          FX_BOOL bDecrypt);
 
-  CPDF_Object* GetObjectByStrict(CPDF_IndirectObjects* pObjList,
+  CPDF_Object* GetObjectByStrict(CPDF_IndirectObjectHolder* pObjList,
                                  FX_DWORD objnum,
                                  FX_DWORD gennum,
                                  PARSE_CONTEXT* pContext);
@@ -403,7 +403,7 @@
 
   CPDF_Dictionary* GetEncryptDict() { return m_pEncryptDict; }
 
-  CPDF_Object* ParseIndirectObject(CPDF_IndirectObjects* pObjList,
+  CPDF_Object* ParseIndirectObject(CPDF_IndirectObjectHolder* pObjList,
                                    FX_DWORD objnum,
                                    PARSE_CONTEXT* pContext = NULL);
   FX_DWORD GetLastObjNum() const;
@@ -421,16 +421,17 @@
   int GetFileVersion() const { return m_FileVersion; }
 
   FX_BOOL IsXRefStream() const { return m_bXRefStream; }
-  CPDF_Object* ParseIndirectObjectAt(CPDF_IndirectObjects* pObjList,
+  CPDF_Object* ParseIndirectObjectAt(CPDF_IndirectObjectHolder* pObjList,
                                      FX_FILESIZE pos,
                                      FX_DWORD objnum,
                                      PARSE_CONTEXT* pContext);
 
-  CPDF_Object* ParseIndirectObjectAtByStrict(CPDF_IndirectObjects* pObjList,
-                                             FX_FILESIZE pos,
-                                             FX_DWORD objnum,
-                                             PARSE_CONTEXT* pContext,
-                                             FX_FILESIZE* pResultPos);
+  CPDF_Object* ParseIndirectObjectAtByStrict(
+      CPDF_IndirectObjectHolder* pObjList,
+      FX_FILESIZE pos,
+      FX_DWORD objnum,
+      PARSE_CONTEXT* pContext,
+      FX_FILESIZE* pResultPos);
 
   FX_DWORD StartAsynParse(IFX_FileRead* pFile,
                           FX_BOOL bReParse = FALSE,
@@ -795,7 +796,7 @@
   return PDF_EncodeText(str.c_str(), str.GetLength(), pCharMap);
 }
 FX_FLOAT PDF_ClipFloat(FX_FLOAT f);
-class CFDF_Document : public CPDF_IndirectObjects {
+class CFDF_Document : public CPDF_IndirectObjectHolder {
  public:
   static CFDF_Document* CreateNewDoc();
   static CFDF_Document* ParseFile(IFX_FileRead* pFile,
diff --git a/core/src/fpdfapi/fpdf_edit/fpdf_edit_create.cpp b/core/src/fpdfapi/fpdf_edit/fpdf_edit_create.cpp
index 65bb3d9..1ffcfbf 100644
--- a/core/src/fpdfapi/fpdf_edit/fpdf_edit_create.cpp
+++ b/core/src/fpdfapi/fpdf_edit/fpdf_edit_create.cpp
@@ -11,6 +11,7 @@
 #include "core/include/fxcrt/fx_ext.h"
 #include "core/include/fpdfapi/fpdf_serial.h"
 #include "core/include/fpdfapi/fpdf_parser.h"
+#include "third_party/base/stl_util.h"
 
 #define PDF_OBJECTSTREAM_MAXLENGTH (256 * 1024)
 #define PDF_XREFSTREAM_MAXSIZE 10000
@@ -1283,9 +1284,8 @@
     return 0;
   }
   m_ObjectOffset[objnum] = m_Offset;
-  void* valuetemp = NULL;
   FX_BOOL bExistInMap =
-      m_pDocument->m_IndirectObjs.Lookup((void*)(uintptr_t)objnum, valuetemp);
+      pdfium::ContainsKey(m_pDocument->m_IndirectObjs, objnum);
   FX_BOOL bObjStm =
       (m_pParser->m_V5Type[objnum] == 2) && m_pEncryptDict && !m_pXRefStream;
   if (m_pParser->m_bVersionUpdated || m_bSecurityChanged || bExistInMap ||
@@ -1371,14 +1371,13 @@
   int32_t index = (int32_t)(uintptr_t)m_Pos;
   while (index < iCount) {
     FX_DWORD objnum = m_NewObjNumArray.ElementAt(index);
-    CPDF_Object* pObj = NULL;
-    m_pDocument->m_IndirectObjs.Lookup((void*)(uintptr_t)objnum, (void*&)pObj);
-    if (NULL == pObj) {
+    auto it = m_pDocument->m_IndirectObjs.find(objnum);
+    if (it == m_pDocument->m_IndirectObjs.end()) {
       ++index;
       continue;
     }
     m_ObjectOffset[objnum] = m_Offset;
-    if (WriteIndirectObj(pObj)) {
+    if (WriteIndirectObj(it->second)) {
       return -1;
     }
     index++;
@@ -1416,24 +1415,17 @@
 void CPDF_Creator::InitNewObjNumOffsets() {
   FX_BOOL bIncremental = (m_dwFlags & FPDFCREATE_INCREMENTAL) != 0;
   FX_BOOL bNoOriginal = (m_dwFlags & FPDFCREATE_NO_ORIGINAL) != 0;
-  FX_POSITION pos = m_pDocument->m_IndirectObjs.GetStartPosition();
-  while (pos) {
-    size_t key = 0;
-    CPDF_Object* pObj;
-    m_pDocument->m_IndirectObjs.GetNextAssoc(pos, (void*&)key, (void*&)pObj);
-    FX_DWORD objnum = (FX_DWORD)key;
-    if (pObj->GetObjNum() == -1) {
+  for (const auto& pair : m_pDocument->m_IndirectObjs) {
+    if (pair.second->GetObjNum() == -1)
       continue;
-    }
     if (bIncremental) {
-      if (!pObj->IsModified()) {
+      if (!pair.second->IsModified())
         continue;
-      }
-    } else if (m_pParser && m_pParser->IsValidObjectNumber(objnum) &&
-               m_pParser->m_V5Type[objnum]) {
+    } else if (m_pParser && m_pParser->IsValidObjectNumber(pair.first) &&
+               m_pParser->m_V5Type[pair.first]) {
       continue;
     }
-    AppendNewObjNum(objnum);
+    AppendNewObjNum(pair.first);
   }
   int32_t iCount = m_NewObjNumArray.GetSize();
   if (iCount == 0) {
diff --git a/core/src/fpdfapi/fpdf_edit/fpdf_edit_doc.cpp b/core/src/fpdfapi/fpdf_edit/fpdf_edit_doc.cpp
index e1c39fb..9fa196f 100644
--- a/core/src/fpdfapi/fpdf_edit/fpdf_edit_doc.cpp
+++ b/core/src/fpdfapi/fpdf_edit/fpdf_edit_doc.cpp
@@ -10,7 +10,7 @@
 #include "core/include/fpdfapi/fpdf_page.h"
 #include "core/src/fpdfapi/fpdf_page/pageint.h"
 
-CPDF_Document::CPDF_Document() : CPDF_IndirectObjects(NULL) {
+CPDF_Document::CPDF_Document() : CPDF_IndirectObjectHolder(NULL) {
   m_pRootDict = NULL;
   m_pInfoDict = NULL;
   m_bLinearized = FALSE;
diff --git a/core/src/fpdfapi/fpdf_parser/fpdf_parser_document.cpp b/core/src/fpdfapi/fpdf_parser/fpdf_parser_document.cpp
index 7353bfa..d8091e8 100644
--- a/core/src/fpdfapi/fpdf_parser/fpdf_parser_document.cpp
+++ b/core/src/fpdfapi/fpdf_parser/fpdf_parser_document.cpp
@@ -9,7 +9,7 @@
 #include "core/include/fpdfapi/fpdf_module.h"
 
 CPDF_Document::CPDF_Document(CPDF_Parser* pParser)
-    : CPDF_IndirectObjects(pParser) {
+    : CPDF_IndirectObjectHolder(pParser) {
   ASSERT(pParser);
   m_pRootDict = NULL;
   m_pInfoDict = NULL;
@@ -332,13 +332,11 @@
   return !m_pParser || m_pParser->IsOwner();
 }
 FX_BOOL CPDF_Document::IsFormStream(FX_DWORD objnum, FX_BOOL& bForm) const {
-  {
-    CPDF_Object* pObj;
-    if (m_IndirectObjs.Lookup((void*)(uintptr_t)objnum, (void*&)pObj)) {
-      CPDF_Stream* pStream = pObj->AsStream();
-      bForm = pStream && pStream->GetDict()->GetString("Subtype") == "Form";
-      return TRUE;
-    }
+  auto it = m_IndirectObjs.find(objnum);
+  if (it != m_IndirectObjs.end()) {
+    CPDF_Stream* pStream = it->second->AsStream();
+    bForm = pStream && pStream->GetDict()->GetString("Subtype") == "Form";
+    return TRUE;
   }
   if (!m_pParser) {
     bForm = FALSE;
diff --git a/core/src/fpdfapi/fpdf_parser/fpdf_parser_fdf.cpp b/core/src/fpdfapi/fpdf_parser/fpdf_parser_fdf.cpp
index d0ca02c..5471449 100644
--- a/core/src/fpdfapi/fpdf_parser/fpdf_parser_fdf.cpp
+++ b/core/src/fpdfapi/fpdf_parser/fpdf_parser_fdf.cpp
@@ -8,7 +8,7 @@
 
 #include "core/include/fpdfapi/fpdf_serial.h"
 
-CFDF_Document::CFDF_Document() : CPDF_IndirectObjects(NULL) {
+CFDF_Document::CFDF_Document() : CPDF_IndirectObjectHolder(NULL) {
   m_pRootDict = NULL;
   m_pFile = NULL;
   m_bOwnFile = FALSE;
@@ -87,12 +87,8 @@
     return FALSE;
   }
   buf << "%FDF-1.2\r\n";
-  FX_POSITION pos = m_IndirectObjs.GetStartPosition();
-  while (pos) {
-    size_t objnum;
-    CPDF_Object* pObj;
-    m_IndirectObjs.GetNextAssoc(pos, (void*&)objnum, (void*&)pObj);
-    buf << (FX_DWORD)objnum << " 0 obj\r\n" << pObj << "\r\nendobj\r\n\r\n";
+  for (const auto& pair : m_IndirectObjs) {
+    buf << pair.first << " 0 obj\r\n" << pair.second << "\r\nendobj\r\n\r\n";
   }
   buf << "trailer\r\n<</Root " << m_pRootDict->GetObjNum()
       << " 0 R>>\r\n%%EOF\r\n";
diff --git a/core/src/fpdfapi/fpdf_parser/fpdf_parser_objects.cpp b/core/src/fpdfapi/fpdf_parser/fpdf_parser_objects.cpp
index 2cb8100..e0ce3fa 100644
--- a/core/src/fpdfapi/fpdf_parser/fpdf_parser_objects.cpp
+++ b/core/src/fpdfapi/fpdf_parser/fpdf_parser_objects.cpp
@@ -6,6 +6,8 @@
 
 #include "core/include/fpdfapi/fpdf_objects.h"
 
+#include <algorithm>
+
 #include "core/include/fpdfapi/fpdf_parser.h"
 #include "core/include/fxcrt/fx_string.h"
 #include "third_party/base/stl_util.h"
@@ -147,7 +149,7 @@
       return AsStream()->GetDict();
     case PDFOBJ_REFERENCE: {
       const CPDF_Reference* pRef = AsReference();
-      CPDF_IndirectObjects* pIndirect = pRef->GetObjList();
+      CPDF_IndirectObjectHolder* pIndirect = pRef->GetObjList();
       if (!pIndirect)
         return nullptr;
       CPDF_Object* pObj =
@@ -300,7 +302,7 @@
   }
   return NULL;
 }
-CPDF_Object* CPDF_Object::CloneRef(CPDF_IndirectObjects* pDoc) const {
+CPDF_Object* CPDF_Object::CloneRef(CPDF_IndirectObjectHolder* pDoc) const {
   if (m_ObjNum) {
     return new CPDF_Reference(pDoc, m_ObjNum);
   }
@@ -513,7 +515,7 @@
 }
 void CPDF_Array::SetAt(FX_DWORD i,
                        CPDF_Object* pObj,
-                       CPDF_IndirectObjects* pObjs) {
+                       CPDF_IndirectObjectHolder* pObjs) {
   ASSERT(IsArray());
   ASSERT(i < (FX_DWORD)m_Objects.GetSize());
   if (i >= (FX_DWORD)m_Objects.GetSize())
@@ -528,14 +530,14 @@
 }
 void CPDF_Array::InsertAt(FX_DWORD index,
                           CPDF_Object* pObj,
-                          CPDF_IndirectObjects* pObjs) {
+                          CPDF_IndirectObjectHolder* pObjs) {
   if (pObj->GetObjNum()) {
     ASSERT(pObjs);
     pObj = new CPDF_Reference(pObjs, pObj->GetObjNum());
   }
   m_Objects.InsertAt(index, pObj);
 }
-void CPDF_Array::Add(CPDF_Object* pObj, CPDF_IndirectObjects* pObjs) {
+void CPDF_Array::Add(CPDF_Object* pObj, CPDF_IndirectObjectHolder* pObjs) {
   if (pObj->GetObjNum()) {
     ASSERT(pObjs);
     pObj = new CPDF_Reference(pObjs, pObj->GetObjNum());
@@ -560,7 +562,8 @@
   pNumber->SetNumber(f);
   Add(pNumber);
 }
-void CPDF_Array::AddReference(CPDF_IndirectObjects* pDoc, FX_DWORD objnum) {
+void CPDF_Array::AddReference(CPDF_IndirectObjectHolder* pDoc,
+                              FX_DWORD objnum) {
   ASSERT(IsArray());
   Add(new CPDF_Reference(pDoc, objnum));
 }
@@ -765,12 +768,12 @@
   SetAt(key, new CPDF_String(str, FALSE));
 }
 void CPDF_Dictionary::SetAtReference(const CFX_ByteStringC& key,
-                                     CPDF_IndirectObjects* pDoc,
+                                     CPDF_IndirectObjectHolder* pDoc,
                                      FX_DWORD objnum) {
   SetAt(key, new CPDF_Reference(pDoc, objnum));
 }
 void CPDF_Dictionary::AddReference(const CFX_ByteStringC& key,
-                                   CPDF_IndirectObjects* pDoc,
+                                   CPDF_IndirectObjectHolder* pDoc,
                                    FX_DWORD objnum) {
   SetAt(key, new CPDF_Reference(pDoc, objnum));
 }
@@ -1049,111 +1052,88 @@
   FXSYS_memcpy(p, m_pData, m_dwSize);
   return p;
 }
-void CPDF_Reference::SetRef(CPDF_IndirectObjects* pDoc, FX_DWORD objnum) {
+void CPDF_Reference::SetRef(CPDF_IndirectObjectHolder* pDoc, FX_DWORD objnum) {
   m_pObjList = pDoc;
   m_RefObjNum = objnum;
 }
-CPDF_IndirectObjects::CPDF_IndirectObjects(CPDF_Parser* pParser) {
-  m_pParser = pParser;
-  m_IndirectObjs.InitHashTable(1013);
-  if (pParser) {
+CPDF_IndirectObjectHolder::CPDF_IndirectObjectHolder(CPDF_Parser* pParser)
+    : m_pParser(pParser), m_LastObjNum(0) {
+  if (pParser)
     m_LastObjNum = m_pParser->GetLastObjNum();
-  } else {
-    m_LastObjNum = 0;
+}
+CPDF_IndirectObjectHolder::~CPDF_IndirectObjectHolder() {
+  for (const auto& pair : m_IndirectObjs) {
+    pair.second->Destroy();
   }
 }
-CPDF_IndirectObjects::~CPDF_IndirectObjects() {
-  FX_POSITION pos = m_IndirectObjs.GetStartPosition();
-  while (pos) {
-    void* key;
-    void* value;
-    m_IndirectObjs.GetNextAssoc(pos, key, value);
-    static_cast<CPDF_Object*>(value)->Destroy();
-  }
-}
-CPDF_Object* CPDF_IndirectObjects::GetIndirectObject(FX_DWORD objnum,
-                                                     PARSE_CONTEXT* pContext) {
+CPDF_Object* CPDF_IndirectObjectHolder::GetIndirectObject(
+    FX_DWORD objnum,
+    PARSE_CONTEXT* pContext) {
   if (objnum == 0)
     return nullptr;
-  void* value;
-  if (m_IndirectObjs.Lookup((void*)(uintptr_t)objnum, value)) {
-    CPDF_Object* pValue = static_cast<CPDF_Object*>(value);
-    if (pValue->GetObjNum() == -1)
-      return nullptr;
-    return pValue;
-  }
 
-  CPDF_Object* pObj = nullptr;
-  if (m_pParser)
-    pObj = m_pParser->ParseIndirectObject(this, objnum, pContext);
+  auto it = m_IndirectObjs.find(objnum);
+  if (it != m_IndirectObjs.end())
+    return it->second->GetObjNum() != -1 ? it->second : nullptr;
+
+  if (!m_pParser)
+    return nullptr;
+
+  CPDF_Object* pObj = m_pParser->ParseIndirectObject(this, objnum, pContext);
   if (!pObj)
     return nullptr;
 
   pObj->m_ObjNum = objnum;
-  if (m_LastObjNum < objnum) {
-    m_LastObjNum = objnum;
-  }
-  if (m_IndirectObjs.Lookup((void*)(uintptr_t)objnum, value)) {
-    if (value)
-      static_cast<CPDF_Object*>(value)->Destroy();
-  }
-  m_IndirectObjs.SetAt((void*)(uintptr_t)objnum, pObj);
+  m_LastObjNum = std::max(m_LastObjNum, objnum);
+  if (m_IndirectObjs[objnum])
+    m_IndirectObjs[objnum]->Destroy();
+
+  m_IndirectObjs[objnum] = pObj;
   return pObj;
 }
-int CPDF_IndirectObjects::GetIndirectType(FX_DWORD objnum) {
-  void* value;
-  if (m_IndirectObjs.Lookup((void*)(uintptr_t)objnum, value))
-    return static_cast<CPDF_Object*>(value)->GetType();
+int CPDF_IndirectObjectHolder::GetIndirectType(FX_DWORD objnum) {
+  auto it = m_IndirectObjs.find(objnum);
+  if (it != m_IndirectObjs.end())
+    return it->second->GetType();
 
-  if (m_pParser) {
-    PARSE_CONTEXT context;
-    FXSYS_memset(&context, 0, sizeof(PARSE_CONTEXT));
-    context.m_Flags = PDFPARSE_TYPEONLY;
-    return (int)(uintptr_t)m_pParser->ParseIndirectObject(this, objnum,
-                                                          &context);
-  }
-  return 0;
+  if (!m_pParser)
+    return 0;
+
+  PARSE_CONTEXT context;
+  FXSYS_memset(&context, 0, sizeof(PARSE_CONTEXT));
+  context.m_Flags = PDFPARSE_TYPEONLY;
+  return (int)(uintptr_t)m_pParser->ParseIndirectObject(this, objnum, &context);
 }
-FX_DWORD CPDF_IndirectObjects::AddIndirectObject(CPDF_Object* pObj) {
+FX_DWORD CPDF_IndirectObjectHolder::AddIndirectObject(CPDF_Object* pObj) {
   if (pObj->m_ObjNum) {
     return pObj->m_ObjNum;
   }
   m_LastObjNum++;
-  m_IndirectObjs.SetAt((void*)(uintptr_t)m_LastObjNum, pObj);
+  m_IndirectObjs[m_LastObjNum] = pObj;
   pObj->m_ObjNum = m_LastObjNum;
   return m_LastObjNum;
 }
-void CPDF_IndirectObjects::ReleaseIndirectObject(FX_DWORD objnum) {
-  void* value;
-  if (!m_IndirectObjs.Lookup((void*)(uintptr_t)objnum, value))
+void CPDF_IndirectObjectHolder::ReleaseIndirectObject(FX_DWORD objnum) {
+  auto it = m_IndirectObjs.find(objnum);
+  if (it == m_IndirectObjs.end() || it->second->GetObjNum() == -1)
     return;
-  CPDF_Object* pValue = static_cast<CPDF_Object*>(value);
-  if (pValue->GetObjNum() == -1)
-    return;
-  pValue->Destroy();
-  m_IndirectObjs.RemoveKey((void*)(uintptr_t)objnum);
+  it->second->Destroy();
+  m_IndirectObjs.erase(it);
 }
-FX_BOOL CPDF_IndirectObjects::InsertIndirectObject(FX_DWORD objnum,
-                                                   CPDF_Object* pObj) {
+FX_BOOL CPDF_IndirectObjectHolder::InsertIndirectObject(FX_DWORD objnum,
+                                                        CPDF_Object* pObj) {
   if (!objnum || !pObj)
     return FALSE;
-  void* value = nullptr;
-  if (m_IndirectObjs.Lookup((void*)(uintptr_t)objnum, value)) {
-    if (value) {
-      CPDF_Object* pExistingObj = static_cast<CPDF_Object*>(value);
-      if (pObj->GetGenNum() <= pExistingObj->GetGenNum()) {
-        pObj->Destroy();
-        return FALSE;
-      }
-      pExistingObj->Destroy();
+  auto it = m_IndirectObjs.find(objnum);
+  if (it != m_IndirectObjs.end()) {
+    if (pObj->GetGenNum() <= it->second->GetGenNum()) {
+      pObj->Destroy();
+      return FALSE;
     }
+    it->second->Destroy();
   }
   pObj->m_ObjNum = objnum;
-  m_IndirectObjs.SetAt((void*)(uintptr_t)objnum, pObj);
-  if (m_LastObjNum < objnum)
-    m_LastObjNum = objnum;
+  m_IndirectObjs[objnum] = pObj;
+  m_LastObjNum = std::max(m_LastObjNum, objnum);
   return TRUE;
 }
-FX_DWORD CPDF_IndirectObjects::GetLastObjNum() const {
-  return m_LastObjNum;
-}
diff --git a/core/src/fpdfapi/fpdf_parser/fpdf_parser_parser.cpp b/core/src/fpdfapi/fpdf_parser/fpdf_parser_parser.cpp
index 49d6760..777d14c 100644
--- a/core/src/fpdfapi/fpdf_parser/fpdf_parser_parser.cpp
+++ b/core/src/fpdfapi/fpdf_parser/fpdf_parser_parser.cpp
@@ -1199,9 +1199,10 @@
   return TRUE;
 }
 
-CPDF_Object* CPDF_Parser::ParseIndirectObject(CPDF_IndirectObjects* pObjList,
-                                              FX_DWORD objnum,
-                                              PARSE_CONTEXT* pContext) {
+CPDF_Object* CPDF_Parser::ParseIndirectObject(
+    CPDF_IndirectObjectHolder* pObjList,
+    FX_DWORD objnum,
+    PARSE_CONTEXT* pContext) {
   if (!IsValidObjectNumber(objnum))
     return nullptr;
 
@@ -1397,10 +1398,11 @@
   m_Syntax.RestorePos(SavedPos);
 }
 
-CPDF_Object* CPDF_Parser::ParseIndirectObjectAt(CPDF_IndirectObjects* pObjList,
-                                                FX_FILESIZE pos,
-                                                FX_DWORD objnum,
-                                                PARSE_CONTEXT* pContext) {
+CPDF_Object* CPDF_Parser::ParseIndirectObjectAt(
+    CPDF_IndirectObjectHolder* pObjList,
+    FX_FILESIZE pos,
+    FX_DWORD objnum,
+    PARSE_CONTEXT* pContext) {
   FX_FILESIZE SavedPos = m_Syntax.SavePos();
   m_Syntax.RestorePos(pos);
   bool bIsNumber;
@@ -1442,7 +1444,7 @@
   return pObj;
 }
 CPDF_Object* CPDF_Parser::ParseIndirectObjectAtByStrict(
-    CPDF_IndirectObjects* pObjList,
+    CPDF_IndirectObjectHolder* pObjList,
     FX_FILESIZE pos,
     FX_DWORD objnum,
     PARSE_CONTEXT* pContext,
@@ -2041,7 +2043,7 @@
   return GetNextWord(nullptr);
 }
 
-CPDF_Object* CPDF_SyntaxParser::GetObject(CPDF_IndirectObjects* pObjList,
+CPDF_Object* CPDF_SyntaxParser::GetObject(CPDF_IndirectObjectHolder* pObjList,
                                           FX_DWORD objnum,
                                           FX_DWORD gennum,
                                           PARSE_CONTEXT* pContext,
@@ -2197,7 +2199,7 @@
 }
 
 CPDF_Object* CPDF_SyntaxParser::GetObjectByStrict(
-    CPDF_IndirectObjects* pObjList,
+    CPDF_IndirectObjectHolder* pObjList,
     FX_DWORD objnum,
     FX_DWORD gennum,
     PARSE_CONTEXT* pContext) {
@@ -2761,9 +2763,10 @@
   void SetStartOffset(FX_FILESIZE dwOffset);
   FX_BOOL GetNextToken(CFX_ByteString& token);
   FX_BOOL GetNextChar(uint8_t& ch);
-  CPDF_Object* ParseIndirectObjectAt(FX_FILESIZE pos,
-                                     FX_DWORD objnum,
-                                     CPDF_IndirectObjects* pObjList = NULL);
+  CPDF_Object* ParseIndirectObjectAt(
+      FX_FILESIZE pos,
+      FX_DWORD objnum,
+      CPDF_IndirectObjectHolder* pObjList = NULL);
   CPDF_Object* GetObject(FX_DWORD objnum,
                          IFX_DownloadHints* pHints,
                          FX_BOOL* pExistInFile);
@@ -3633,7 +3636,7 @@
 CPDF_Object* CPDF_DataAvail::ParseIndirectObjectAt(
     FX_FILESIZE pos,
     FX_DWORD objnum,
-    CPDF_IndirectObjects* pObjList) {
+    CPDF_IndirectObjectHolder* pObjList) {
   FX_FILESIZE SavedPos = m_syntaxParser.SavePos();
   m_syntaxParser.RestorePos(pos);
   bool bIsNumber;