From 67268cd0efa2ebd3b27e963718e90b461e9f73b2 Mon Sep 17 00:00:00 2001 From: Dan Sinclair Date: Wed, 16 May 2018 16:33:02 +0000 Subject: Cleanup CPDF_ContentParser This CL cleans up the CPDF_ContentParser code. The m_bIsDone flag has been removed and a kComplete stage added. Each of the processing methods returns the next stage instead of setting the internal flag automatically. The infinite loop is removed for simpler straight line code. Change-Id: Id817a5fa054e28c331c68c63ec2c12b369cb0233 Reviewed-on: https://pdfium-review.googlesource.com/32611 Commit-Queue: dsinclair Reviewed-by: Henrique Nakashima --- core/fpdfapi/page/cpdf_contentparser.cpp | 131 ++++++++++++++++--------------- core/fpdfapi/page/cpdf_contentparser.h | 22 +++--- 2 files changed, 81 insertions(+), 72 deletions(-) diff --git a/core/fpdfapi/page/cpdf_contentparser.cpp b/core/fpdfapi/page/cpdf_contentparser.cpp index 93c64a14ec..ec39858552 100644 --- a/core/fpdfapi/page/cpdf_contentparser.cpp +++ b/core/fpdfapi/page/cpdf_contentparser.cpp @@ -23,31 +23,35 @@ #define PARSE_STEP_LIMIT 100 CPDF_ContentParser::CPDF_ContentParser(CPDF_Page* pPage) - : m_InternalStage(STAGE_GETCONTENT), m_pObjectHolder(pPage) { + : m_CurrentStage(Stage::kGetContent), m_pObjectHolder(pPage) { if (!pPage || !pPage->GetDocument() || !pPage->GetFormDict()) { - m_bIsDone = true; + m_CurrentStage = Stage::kComplete; return; } CPDF_Object* pContent = pPage->GetFormDict()->GetDirectObjectFor("Contents"); if (!pContent) { - m_bIsDone = true; + m_CurrentStage = Stage::kComplete; return; } + CPDF_Stream* pStream = pContent->AsStream(); if (pStream) { m_pSingleStream = pdfium::MakeRetain(pStream); m_pSingleStream->LoadAllDataFiltered(); + m_CurrentStage = Stage::kPrepareContent; return; } + CPDF_Array* pArray = pContent->AsArray(); if (!pArray) { - m_bIsDone = true; + m_CurrentStage = Stage::kComplete; return; } + m_nStreams = pArray->GetCount(); - if (!m_nStreams) { - m_bIsDone = true; + if (m_nStreams == 0) { + m_CurrentStage = Stage::kComplete; return; } m_StreamArray.resize(m_nStreams); @@ -58,7 +62,7 @@ CPDF_ContentParser::CPDF_ContentParser(CPDF_Form* pForm, const CFX_Matrix* pParentMatrix, CPDF_Type3Char* pType3Char, std::set* parsedSet) - : m_InternalStage(STAGE_PARSE), + : m_CurrentStage(Stage::kParse), m_pObjectHolder(pForm), m_pType3Char(pType3Char) { CFX_Matrix form_matrix = pForm->GetFormDict()->GetMatrixFor("Matrix"); @@ -113,60 +117,29 @@ CPDF_ContentParser::~CPDF_ContentParser() {} // Continue() should be called again. Returning |false| means that we've // completed the parse and Continue() is complete. bool CPDF_ContentParser::Continue(PauseIndicatorIface* pPause) { - if (m_bIsDone) - return false; - - while (true) { - switch (m_InternalStage) { - case STAGE_GETCONTENT: - StageGetContent(); - break; - case STAGE_PARSE: - StageParse(); - break; - case STAGE_CHECKCLIP: - StageCheckClip(); - break; - } - - if (m_bIsDone) - return false; + while (m_CurrentStage == Stage::kGetContent) { + m_CurrentStage = GetContent(); if (pPause && pPause->NeedToPauseNow()) return true; } -} -void CPDF_ContentParser::StageGetContent() { - if (m_CurrentOffset == m_nStreams) { - if (!m_StreamArray.empty()) { - FX_SAFE_UINT32 safeSize = 0; - for (const auto& stream : m_StreamArray) { - safeSize += stream->GetSize(); - safeSize += 1; - } - if (!safeSize.IsValid()) { - m_bIsDone = true; - return; - } - m_Size = safeSize.ValueOrDie(); - m_pData.Reset( - std::unique_ptr(FX_Alloc(uint8_t, m_Size))); - uint32_t pos = 0; - for (const auto& stream : m_StreamArray) { - memcpy(m_pData.Get() + pos, stream->GetData(), stream->GetSize()); - pos += stream->GetSize(); - m_pData.Get()[pos++] = ' '; - } - m_StreamArray.clear(); - } else { - m_pData.Reset(m_pSingleStream->GetData()); - m_Size = m_pSingleStream->GetSize(); - } - m_InternalStage = STAGE_PARSE; - m_CurrentOffset = 0; - return; + if (m_CurrentStage == Stage::kPrepareContent) + m_CurrentStage = PrepareContent(); + + while (m_CurrentStage == Stage::kParse) { + m_CurrentStage = Parse(); + if (pPause && pPause->NeedToPauseNow()) + return true; } + if (m_CurrentStage == Stage::kCheckClip) + m_CurrentStage = CheckClip(); + + ASSERT(m_CurrentStage == Stage::kComplete); + return false; +} + +CPDF_ContentParser::Stage CPDF_ContentParser::GetContent() { CPDF_Array* pContent = m_pObjectHolder->GetFormDict()->GetArrayFor("Contents"); CPDF_Stream* pStreamObj = ToStream( @@ -175,9 +148,44 @@ void CPDF_ContentParser::StageGetContent() { pdfium::MakeRetain(pStreamObj); m_StreamArray[m_CurrentOffset]->LoadAllDataFiltered(); m_CurrentOffset++; + + return m_CurrentOffset == m_nStreams ? Stage::kPrepareContent + : Stage::kGetContent; } -void CPDF_ContentParser::StageParse() { +CPDF_ContentParser::Stage CPDF_ContentParser::PrepareContent() { + m_CurrentOffset = 0; + + if (m_StreamArray.empty()) { + m_pData.Reset(m_pSingleStream->GetData()); + m_Size = m_pSingleStream->GetSize(); + return Stage::kParse; + } + + FX_SAFE_UINT32 safeSize = 0; + for (const auto& stream : m_StreamArray) { + safeSize += stream->GetSize(); + safeSize += 1; + } + if (!safeSize.IsValid()) + return Stage::kComplete; + + m_Size = safeSize.ValueOrDie(); + m_pData.Reset( + std::unique_ptr(FX_Alloc(uint8_t, m_Size))); + + uint32_t pos = 0; + for (const auto& stream : m_StreamArray) { + memcpy(m_pData.Get() + pos, stream->GetData(), stream->GetSize()); + pos += stream->GetSize(); + m_pData.Get()[pos++] = ' '; + } + m_StreamArray.clear(); + + return Stage::kParse; +} + +CPDF_ContentParser::Stage CPDF_ContentParser::Parse() { if (!m_pParser) { m_parsedSet = pdfium::MakeUnique>(); m_pParser = pdfium::MakeUnique( @@ -187,17 +195,16 @@ void CPDF_ContentParser::StageParse() { nullptr, m_parsedSet.get()); m_pParser->GetCurStates()->m_ColorState.SetDefault(); } - if (m_CurrentOffset >= m_Size) { - m_InternalStage = STAGE_CHECKCLIP; - return; - } + if (m_CurrentOffset >= m_Size) + return Stage::kCheckClip; m_CurrentOffset += m_pParser->Parse(m_pData.Get() + m_CurrentOffset, m_Size - m_CurrentOffset, PARSE_STEP_LIMIT); + return Stage::kParse; } -void CPDF_ContentParser::StageCheckClip() { +CPDF_ContentParser::Stage CPDF_ContentParser::CheckClip() { if (m_pType3Char) { m_pType3Char->InitializeFromStreamData(m_pParser->IsColored(), m_pParser->GetType3Data()); @@ -223,5 +230,5 @@ void CPDF_ContentParser::StageCheckClip() { if (old_rect.Contains(obj_rect)) pObj->m_ClipPath.SetNull(); } - m_bIsDone = true; + return Stage::kComplete; } diff --git a/core/fpdfapi/page/cpdf_contentparser.h b/core/fpdfapi/page/cpdf_contentparser.h index d530a1407e..f9b491defa 100644 --- a/core/fpdfapi/page/cpdf_contentparser.h +++ b/core/fpdfapi/page/cpdf_contentparser.h @@ -40,24 +40,26 @@ class CPDF_ContentParser { bool Continue(PauseIndicatorIface* pPause); private: - enum InternalStage { - STAGE_GETCONTENT = 1, - STAGE_PARSE, - STAGE_CHECKCLIP, + enum class Stage : uint8_t { + kGetContent = 1, + kPrepareContent, + kParse, + kCheckClip, + kComplete, }; - void StageGetContent(); - void StageParse(); - void StageCheckClip(); + Stage GetContent(); + Stage PrepareContent(); + Stage Parse(); + Stage CheckClip(); - bool m_bIsDone = false; - InternalStage m_InternalStage; + Stage m_CurrentStage; UnownedPtr const m_pObjectHolder; UnownedPtr m_pType3Char; // Only used when parsing forms. - uint32_t m_nStreams = 0; RetainPtr m_pSingleStream; std::vector> m_StreamArray; MaybeOwned m_pData; + uint32_t m_nStreams = 0; uint32_t m_Size = 0; uint32_t m_CurrentOffset = 0; -- cgit v1.2.3