xref: /aosp_15_r20/external/pdfium/core/fpdfapi/parser/cfdf_document.cpp (revision 3ac0a46f773bac49fa9476ec2b1cf3f8da5ec3a4)
1 // Copyright 2014 The PDFium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
6 
7 #include "core/fpdfapi/parser/cfdf_document.h"
8 
9 #include <memory>
10 #include <sstream>
11 #include <utility>
12 
13 #include "core/fpdfapi/parser/cpdf_dictionary.h"
14 #include "core/fpdfapi/parser/cpdf_syntax_parser.h"
15 #include "core/fpdfapi/parser/fpdf_parser_utility.h"
16 #include "core/fxcrt/cfx_read_only_span_stream.h"
17 #include "core/fxcrt/fx_string_wrappers.h"
18 #include "third_party/base/containers/span.h"
19 
20 CFDF_Document::CFDF_Document() = default;
21 
22 CFDF_Document::~CFDF_Document() = default;
23 
CreateNewDoc()24 std::unique_ptr<CFDF_Document> CFDF_Document::CreateNewDoc() {
25   auto pDoc = std::make_unique<CFDF_Document>();
26   pDoc->m_pRootDict = pDoc->NewIndirect<CPDF_Dictionary>();
27   pDoc->m_pRootDict->SetNewFor<CPDF_Dictionary>("FDF");
28   return pDoc;
29 }
30 
ParseMemory(pdfium::span<const uint8_t> span)31 std::unique_ptr<CFDF_Document> CFDF_Document::ParseMemory(
32     pdfium::span<const uint8_t> span) {
33   auto pDoc = std::make_unique<CFDF_Document>();
34   pDoc->ParseStream(pdfium::MakeRetain<CFX_ReadOnlySpanStream>(span));
35   return pDoc->m_pRootDict ? std::move(pDoc) : nullptr;
36 }
37 
ParseStream(RetainPtr<IFX_SeekableReadStream> pFile)38 void CFDF_Document::ParseStream(RetainPtr<IFX_SeekableReadStream> pFile) {
39   m_pFile = std::move(pFile);
40   CPDF_SyntaxParser parser(m_pFile);
41   while (true) {
42     CPDF_SyntaxParser::WordResult word_result = parser.GetNextWord();
43     if (word_result.is_number) {
44       uint32_t objnum = FXSYS_atoui(word_result.word.c_str());
45       if (!objnum)
46         break;
47 
48       word_result = parser.GetNextWord();
49       if (!word_result.is_number)
50         break;
51 
52       word_result = parser.GetNextWord();
53       if (word_result.word != "obj")
54         break;
55 
56       RetainPtr<CPDF_Object> pObj = parser.GetObjectBody(this);
57       if (!pObj)
58         break;
59 
60       ReplaceIndirectObjectIfHigherGeneration(objnum, std::move(pObj));
61       word_result = parser.GetNextWord();
62       if (word_result.word != "endobj")
63         break;
64     } else {
65       if (word_result.word != "trailer")
66         break;
67 
68       RetainPtr<CPDF_Dictionary> pMainDict =
69           ToDictionary(parser.GetObjectBody(this));
70       if (pMainDict)
71         m_pRootDict = pMainDict->GetMutableDictFor("Root");
72 
73       break;
74     }
75   }
76 }
77 
WriteToString() const78 ByteString CFDF_Document::WriteToString() const {
79   if (!m_pRootDict)
80     return ByteString();
81 
82   fxcrt::ostringstream buf;
83   buf << "%FDF-1.2\r\n";
84   for (const auto& pair : *this)
85     buf << pair.first << " 0 obj\r\n"
86         << pair.second.Get() << "\r\nendobj\r\n\r\n";
87 
88   buf << "trailer\r\n<</Root " << m_pRootDict->GetObjNum()
89       << " 0 R>>\r\n%%EOF\r\n";
90 
91   return ByteString(buf);
92 }
93