Refactor page content parsing code in CPDF_ContentParser.

The page content can be an array or a stream. Make separate functions
for array and stream parsing, and for handling failures.

Change-Id: I9b725d10228ef046195cb46a9a8becf4de2f5d00
Reviewed-on: https://pdfium-review.googlesource.com/c/39874
Commit-Queue: Lei Zhang <thestig@chromium.org>
Reviewed-by: Tom Sepez <tsepez@chromium.org>
diff --git a/core/fpdfapi/page/cpdf_contentparser.cpp b/core/fpdfapi/page/cpdf_contentparser.cpp
index b3b7371..85f1f1a 100644
--- a/core/fpdfapi/page/cpdf_contentparser.cpp
+++ b/core/fpdfapi/page/cpdf_contentparser.cpp
@@ -21,8 +21,6 @@
 #include "core/fxcrt/pauseindicator_iface.h"
 #include "third_party/base/ptr_util.h"
 
-#define PARSE_STEP_LIMIT 100
-
 CPDF_ContentParser::CPDF_ContentParser(CPDF_Page* pPage)
     : m_CurrentStage(Stage::kGetContent), m_pObjectHolder(pPage) {
   ASSERT(pPage);
@@ -34,30 +32,21 @@
   CPDF_Object* pContent =
       pPage->GetDict()->GetDirectObjectFor(pdfium::page_object::kContents);
   if (!pContent) {
-    m_CurrentStage = Stage::kComplete;
+    HandlePageContentFailure();
     return;
   }
 
   CPDF_Stream* pStream = pContent->AsStream();
   if (pStream) {
-    m_pSingleStream = pdfium::MakeRetain<CPDF_StreamAcc>(pStream);
-    m_pSingleStream->LoadAllDataFiltered();
-    m_CurrentStage = Stage::kPrepareContent;
+    HandlePageContentStream(pStream);
     return;
   }
 
   CPDF_Array* pArray = pContent->AsArray();
-  if (!pArray) {
-    m_CurrentStage = Stage::kComplete;
+  if (pArray && HandlePageContentArray(pArray))
     return;
-  }
 
-  m_nStreams = pArray->size();
-  if (m_nStreams == 0) {
-    m_CurrentStage = Stage::kComplete;
-    return;
-  }
-  m_StreamArray.resize(m_nStreams);
+  HandlePageContentFailure();
 }
 
 CPDF_ContentParser::CPDF_ContentParser(CPDF_Form* pForm,
@@ -208,8 +197,9 @@
   if (m_StreamSegmentOffsets.empty())
     m_StreamSegmentOffsets.push_back(0);
 
+  static constexpr uint32_t kParseStepLimit = 100;
   m_CurrentOffset += m_pParser->Parse(m_pData.Get(), m_Size, m_CurrentOffset,
-                                      PARSE_STEP_LIMIT, m_StreamSegmentOffsets);
+                                      kParseStepLimit, m_StreamSegmentOffsets);
   return Stage::kParse;
 }
 
@@ -239,3 +229,22 @@
   }
   return Stage::kComplete;
 }
+
+void CPDF_ContentParser::HandlePageContentStream(CPDF_Stream* pStream) {
+  m_pSingleStream = pdfium::MakeRetain<CPDF_StreamAcc>(pStream);
+  m_pSingleStream->LoadAllDataFiltered();
+  m_CurrentStage = Stage::kPrepareContent;
+}
+
+bool CPDF_ContentParser::HandlePageContentArray(CPDF_Array* pArray) {
+  m_nStreams = pArray->size();
+  if (m_nStreams == 0)
+    return false;
+
+  m_StreamArray.resize(m_nStreams);
+  return true;
+}
+
+void CPDF_ContentParser::HandlePageContentFailure() {
+  m_CurrentStage = Stage::kComplete;
+}
diff --git a/core/fpdfapi/page/cpdf_contentparser.h b/core/fpdfapi/page/cpdf_contentparser.h
index 70be98c..c27342e 100644
--- a/core/fpdfapi/page/cpdf_contentparser.h
+++ b/core/fpdfapi/page/cpdf_contentparser.h
@@ -17,9 +17,11 @@
 #include "core/fxcrt/unowned_ptr.h"
 
 class CPDF_AllStates;
+class CPDF_Array;
 class CPDF_Form;
 class CPDF_Page;
 class CPDF_PageObjectHolder;
+class CPDF_Stream;
 class CPDF_StreamAcc;
 class CPDF_Type3Char;
 
@@ -53,6 +55,10 @@
   Stage Parse();
   Stage CheckClip();
 
+  void HandlePageContentStream(CPDF_Stream* pStream);
+  bool HandlePageContentArray(CPDF_Array* pArray);
+  void HandlePageContentFailure();
+
   Stage m_CurrentStage;
   UnownedPtr<CPDF_PageObjectHolder> const m_pObjectHolder;
   UnownedPtr<CPDF_Type3Char> m_pType3Char;  // Only used when parsing forms.