Add a ReadArrayElementsToVector() helper function.

For filling in std::vector<float> from CPDF_Array.

Change-Id: I4227f7e21d02976aa20c2806cb568ce661c01e6a
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/54870
Reviewed-by: Tom Sepez <tsepez@chromium.org>
Commit-Queue: Lei Zhang <thestig@chromium.org>
diff --git a/core/fpdfapi/page/cpdf_allstates.cpp b/core/fpdfapi/page/cpdf_allstates.cpp
index fd5eaa3..2485a06 100644
--- a/core/fpdfapi/page/cpdf_allstates.cpp
+++ b/core/fpdfapi/page/cpdf_allstates.cpp
@@ -14,6 +14,7 @@
 #include "core/fpdfapi/page/cpdf_streamcontentparser.h"
 #include "core/fpdfapi/parser/cpdf_array.h"
 #include "core/fpdfapi/parser/cpdf_dictionary.h"
+#include "core/fpdfapi/parser/fpdf_parser_utility.h"
 #include "core/fxge/cfx_graphstatedata.h"
 #include "third_party/base/compiler_specific.h"
 #include "third_party/base/stl_util.h"
@@ -37,9 +38,7 @@
 void CPDF_AllStates::SetLineDash(const CPDF_Array* pArray,
                                  float phase,
                                  float scale) {
-  std::vector<float> dashes(pArray->size());
-  for (size_t i = 0; i < pArray->size(); ++i)
-    dashes[i] = pArray->GetNumberAt(i);
+  std::vector<float> dashes = ReadArrayElementsToVector(pArray, pArray->size());
   m_GraphState.SetLineDash(std::move(dashes), phase, scale);
 }
 
diff --git a/core/fpdfapi/page/cpdf_colorspace.cpp b/core/fpdfapi/page/cpdf_colorspace.cpp
index 9d054ca..a52a0a8 100644
--- a/core/fpdfapi/page/cpdf_colorspace.cpp
+++ b/core/fpdfapi/page/cpdf_colorspace.cpp
@@ -28,6 +28,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/fxcodec/codec/ccodec_iccmodule.h"
 #include "core/fxcodec/fx_codec.h"
 #include "core/fxcrt/fx_memory.h"
@@ -1062,13 +1063,11 @@
   ASSERT(IsValidComponents(nComponents));
 
   std::vector<float> ranges;
-  ranges.reserve(nComponents * 2);
   const CPDF_Array* pRanges = pDict->GetArrayFor("Range");
   if (pRanges) {
-    for (uint32_t i = 0; i < nComponents * 2; i++) {
-      ranges.push_back(pRanges->GetNumberAt(i));
-    }
+    ranges = ReadArrayElementsToVector(pRanges, nComponents * 2);
   } else {
+    ranges.reserve(nComponents * 2);
     for (uint32_t i = 0; i < nComponents; i++) {
       ranges.push_back(0.0f);
       ranges.push_back(1.0f);
diff --git a/core/fpdfapi/page/cpdf_function.cpp b/core/fpdfapi/page/cpdf_function.cpp
index d6bde12..688c48e 100644
--- a/core/fpdfapi/page/cpdf_function.cpp
+++ b/core/fpdfapi/page/cpdf_function.cpp
@@ -15,6 +15,7 @@
 #include "core/fpdfapi/parser/cpdf_array.h"
 #include "core/fpdfapi/parser/cpdf_dictionary.h"
 #include "core/fpdfapi/parser/cpdf_stream.h"
+#include "core/fpdfapi/parser/fpdf_parser_utility.h"
 #include "core/fxcrt/fx_safe_types.h"
 #include "third_party/base/ptr_util.h"
 #include "third_party/base/stl_util.h"
@@ -92,9 +93,7 @@
     return false;
 
   size_t nInputs = m_nInputs * 2;
-  m_Domains = std::vector<float>(nInputs);
-  for (size_t i = 0; i < nInputs; ++i)
-    m_Domains[i] = pDomains->GetNumberAt(i);
+  m_Domains = ReadArrayElementsToVector(pDomains, nInputs);
 
   const CPDF_Array* pRanges = pDict->GetArrayFor("Range");
   m_nOutputs = pRanges ? pRanges->size() / 2 : 0;
@@ -108,9 +107,7 @@
 
   if (m_nOutputs > 0) {
     size_t nOutputs = m_nOutputs * 2;
-    m_Ranges = std::vector<float>(nOutputs);
-    for (size_t i = 0; i < nOutputs; ++i)
-      m_Ranges[i] = pRanges->GetNumberAt(i);
+    m_Ranges = ReadArrayElementsToVector(pRanges, nOutputs);
   }
 
   uint32_t old_outputs = m_nOutputs;
diff --git a/core/fpdfapi/page/cpdf_stitchfunc.cpp b/core/fpdfapi/page/cpdf_stitchfunc.cpp
index 95d920e..1ec48ac 100644
--- a/core/fpdfapi/page/cpdf_stitchfunc.cpp
+++ b/core/fpdfapi/page/cpdf_stitchfunc.cpp
@@ -10,6 +10,7 @@
 
 #include "core/fpdfapi/parser/cpdf_array.h"
 #include "core/fpdfapi/parser/cpdf_dictionary.h"
+#include "core/fpdfapi/parser/fpdf_parser_utility.h"
 #include "core/fxcrt/fx_safe_types.h"
 
 namespace {
@@ -101,9 +102,7 @@
     m_bounds.push_back(pBoundsArray->GetNumberAt(i));
   m_bounds.push_back(m_Domains[1]);
 
-  m_encode.reserve(nSubs * 2);
-  for (uint32_t i = 0; i < nSubs * 2; i++)
-    m_encode.push_back(pEncodeArray->GetNumberAt(i));
+  m_encode = ReadArrayElementsToVector(pEncodeArray, nSubs * 2);
   return true;
 }
 
diff --git a/core/fpdfapi/parser/fpdf_parser_utility.cpp b/core/fpdfapi/parser/fpdf_parser_utility.cpp
index ec42087..540aabd 100644
--- a/core/fpdfapi/parser/fpdf_parser_utility.cpp
+++ b/core/fpdfapi/parser/fpdf_parser_utility.cpp
@@ -152,6 +152,16 @@
   return res;
 }
 
+std::vector<float> ReadArrayElementsToVector(const CPDF_Array* pArray,
+                                             size_t nCount) {
+  ASSERT(pArray);
+  ASSERT(pArray->size() >= nCount);
+  std::vector<float> ret(nCount);
+  for (size_t i = 0; i < nCount; ++i)
+    ret[i] = pArray->GetNumberAt(i);
+  return ret;
+}
+
 std::ostream& operator<<(std::ostream& buf, const CPDF_Object* pObj) {
   if (!pObj) {
     buf << " null";
diff --git a/core/fpdfapi/parser/fpdf_parser_utility.h b/core/fpdfapi/parser/fpdf_parser_utility.h
index 93a991c..29dd246 100644
--- a/core/fpdfapi/parser/fpdf_parser_utility.h
+++ b/core/fpdfapi/parser/fpdf_parser_utility.h
@@ -8,11 +8,13 @@
 #define CORE_FPDFAPI_PARSER_FPDF_PARSER_UTILITY_H_
 
 #include <ostream>
+#include <vector>
 
 #include "core/fxcrt/fx_string.h"
 #include "core/fxcrt/retain_ptr.h"
 #include "third_party/base/optional.h"
 
+class CPDF_Array;
 class CPDF_Dictionary;
 class CPDF_Object;
 class IFX_SeekableReadStream;
@@ -48,6 +50,11 @@
 ByteString PDF_NameDecode(ByteStringView orig);
 ByteString PDF_NameEncode(const ByteString& orig);
 
+// Return |nCount| elements from |pArray| as a vector of floats. |pArray| must
+// have at least |nCount| elements.
+std::vector<float> ReadArrayElementsToVector(const CPDF_Array* pArray,
+                                             size_t nCount);
+
 std::ostream& operator<<(std::ostream& buf, const CPDF_Object* pObj);
 
 #endif  // CORE_FPDFAPI_PARSER_FPDF_PARSER_UTILITY_H_
diff --git a/core/fpdfapi/render/cpdf_dibbase.cpp b/core/fpdfapi/render/cpdf_dibbase.cpp
index 696cad5..4f1d7e5 100644
--- a/core/fpdfapi/render/cpdf_dibbase.cpp
+++ b/core/fpdfapi/render/cpdf_dibbase.cpp
@@ -21,6 +21,7 @@
 #include "core/fpdfapi/parser/cpdf_stream.h"
 #include "core/fpdfapi/parser/cpdf_stream_acc.h"
 #include "core/fpdfapi/parser/fpdf_parser_decode.h"
+#include "core/fpdfapi/parser/fpdf_parser_utility.h"
 #include "core/fpdfapi/render/cpdf_pagerendercache.h"
 #include "core/fpdfapi/render/cpdf_renderstatus.h"
 #include "core/fxcodec/codec/ccodec_basicmodule.h"
@@ -649,9 +650,8 @@
   const CPDF_Array* pMatte = m_pMaskStream->GetDict()->GetArrayFor("Matte");
   if (pMatte && m_pColorSpace && m_Family != PDFCS_PATTERN &&
       m_pColorSpace->CountComponents() <= m_nComponents) {
-    std::vector<float> colors(m_nComponents);
-    for (uint32_t i = 0; i < m_nComponents; i++)
-      colors[i] = pMatte->GetNumberAt(i);
+    std::vector<float> colors =
+        ReadArrayElementsToVector(pMatte, m_nComponents);
 
     float R;
     float G;
diff --git a/core/fpdfapi/render/cpdf_renderstatus.cpp b/core/fpdfapi/render/cpdf_renderstatus.cpp
index 1c28227..dce3828 100644
--- a/core/fpdfapi/render/cpdf_renderstatus.cpp
+++ b/core/fpdfapi/render/cpdf_renderstatus.cpp
@@ -37,6 +37,7 @@
 #include "core/fpdfapi/parser/cpdf_dictionary.h"
 #include "core/fpdfapi/parser/cpdf_document.h"
 #include "core/fpdfapi/parser/cpdf_stream.h"
+#include "core/fpdfapi/parser/fpdf_parser_utility.h"
 #include "core/fpdfapi/render/cpdf_charposlist.h"
 #include "core/fpdfapi/render/cpdf_devicebuffer.h"
 #include "core/fpdfapi/render/cpdf_dibbase.h"
@@ -2019,9 +2020,9 @@
   if (!pPattern->IsShadingObject() && pDict->KeyExist("Background")) {
     const CPDF_Array* pBackColor = pDict->GetArrayFor("Background");
     if (pBackColor && pBackColor->size() >= pColorSpace->CountComponents()) {
-      std::vector<float> comps(pColorSpace->CountComponents());
-      for (uint32_t i = 0; i < pColorSpace->CountComponents(); i++)
-        comps[i] = pBackColor->GetNumberAt(i);
+      std::vector<float> comps =
+          ReadArrayElementsToVector(pBackColor, pColorSpace->CountComponents());
+
       float R = 0.0f;
       float G = 0.0f;
       float B = 0.0f;
@@ -2626,10 +2627,9 @@
   *pCSFamily = family;
 
   uint32_t comps = std::max(8u, pCS->CountComponents());
-  std::vector<float> floats(comps);
   size_t count = std::min<size_t>(8, pBC->size());
-  for (size_t i = 0; i < count; i++)
-    floats[i] = pBC->GetNumberAt(i);
+  std::vector<float> floats = ReadArrayElementsToVector(pBC, count);
+  floats.resize(comps);
 
   float R;
   float G;
diff --git a/core/fpdfdoc/cpdf_annot.cpp b/core/fpdfdoc/cpdf_annot.cpp
index adc6f53..a4381f9 100644
--- a/core/fpdfdoc/cpdf_annot.cpp
+++ b/core/fpdfdoc/cpdf_annot.cpp
@@ -17,6 +17,7 @@
 #include "core/fpdfapi/parser/cpdf_boolean.h"
 #include "core/fpdfapi/parser/cpdf_dictionary.h"
 #include "core/fpdfapi/parser/cpdf_document.h"
+#include "core/fpdfapi/parser/fpdf_parser_utility.h"
 #include "core/fpdfapi/render/cpdf_rendercontext.h"
 #include "core/fpdfapi/render/cpdf_renderoptions.h"
 #include "core/fpdfdoc/cpvt_generateap.h"
@@ -497,18 +498,10 @@
   graph_state.m_LineWidth = width;
   if (style_char == 'D') {
     if (pDashArray) {
-      size_t dash_count = pDashArray->size();
-      if (dash_count % 2) {
-        dash_count++;
-      }
-      graph_state.m_DashArray.resize(dash_count);
-      size_t i;
-      for (i = 0; i < pDashArray->size(); ++i) {
-        graph_state.m_DashArray[i] = pDashArray->GetNumberAt(i);
-      }
-      if (i < dash_count) {
-        graph_state.m_DashArray[i] = graph_state.m_DashArray[i - 1];
-      }
+      graph_state.m_DashArray =
+          ReadArrayElementsToVector(pDashArray, pDashArray->size());
+      if (graph_state.m_DashArray.size() % 2)
+        graph_state.m_DashArray.push_back(graph_state.m_DashArray.back());
     } else {
       graph_state.m_DashArray = {3.0f, 3.0f};
     }