| // Copyright 2014 PDFium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com |
| |
| #include "core/fpdfapi/parser/cfdf_document.h" |
| |
| #include <memory> |
| #include <sstream> |
| #include <utility> |
| |
| #include "core/fpdfapi/parser/cpdf_dictionary.h" |
| #include "core/fpdfapi/parser/cpdf_syntax_parser.h" |
| #include "core/fpdfapi/parser/fpdf_parser_utility.h" |
| #include "core/fxcrt/cfx_readonlymemorystream.h" |
| #include "third_party/base/span.h" |
| |
| CFDF_Document::CFDF_Document() = default; |
| |
| CFDF_Document::~CFDF_Document() = default; |
| |
| std::unique_ptr<CFDF_Document> CFDF_Document::CreateNewDoc() { |
| auto pDoc = std::make_unique<CFDF_Document>(); |
| pDoc->m_pRootDict.Reset(pDoc->NewIndirect<CPDF_Dictionary>()); |
| pDoc->m_pRootDict->SetNewFor<CPDF_Dictionary>("FDF"); |
| return pDoc; |
| } |
| |
| std::unique_ptr<CFDF_Document> CFDF_Document::ParseMemory( |
| pdfium::span<const uint8_t> span) { |
| auto pDoc = std::make_unique<CFDF_Document>(); |
| pDoc->ParseStream(pdfium::MakeRetain<CFX_ReadOnlyMemoryStream>(span)); |
| return pDoc->m_pRootDict ? std::move(pDoc) : nullptr; |
| } |
| |
| void CFDF_Document::ParseStream(RetainPtr<IFX_SeekableReadStream> pFile) { |
| m_pFile = std::move(pFile); |
| CPDF_SyntaxParser parser(m_pFile); |
| while (1) { |
| CPDF_SyntaxParser::WordResult word_result = parser.GetNextWord(); |
| if (word_result.is_number) { |
| uint32_t objnum = FXSYS_atoui(word_result.word.c_str()); |
| if (!objnum) |
| break; |
| |
| word_result = parser.GetNextWord(); |
| if (!word_result.is_number) |
| break; |
| |
| word_result = parser.GetNextWord(); |
| if (word_result.word != "obj") |
| break; |
| |
| RetainPtr<CPDF_Object> pObj = parser.GetObjectBody(this); |
| if (!pObj) |
| break; |
| |
| ReplaceIndirectObjectIfHigherGeneration(objnum, std::move(pObj)); |
| word_result = parser.GetNextWord(); |
| if (word_result.word != "endobj") |
| break; |
| } else { |
| if (word_result.word != "trailer") |
| break; |
| |
| RetainPtr<CPDF_Dictionary> pMainDict = |
| ToDictionary(parser.GetObjectBody(this)); |
| if (pMainDict) |
| m_pRootDict.Reset(pMainDict->GetDictFor("Root")); |
| |
| break; |
| } |
| } |
| } |
| |
| ByteString CFDF_Document::WriteToString() const { |
| if (!m_pRootDict) |
| return ByteString(); |
| |
| std::ostringstream buf; |
| buf << "%FDF-1.2\r\n"; |
| for (const auto& pair : *this) |
| buf << pair.first << " 0 obj\r\n" |
| << pair.second.Get() << "\r\nendobj\r\n\r\n"; |
| |
| buf << "trailer\r\n<</Root " << m_pRootDict->GetObjNum() |
| << " 0 R>>\r\n%%EOF\r\n"; |
| |
| return ByteString(buf); |
| } |