1 // Copyright 2016 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/cpdf_reference.h"
8
9 #include "core/fpdfapi/parser/cpdf_dictionary.h"
10 #include "core/fpdfapi/parser/cpdf_indirect_object_holder.h"
11 #include "core/fxcrt/fx_stream.h"
12 #include "third_party/base/check_op.h"
13 #include "third_party/base/containers/contains.h"
14
CPDF_Reference(CPDF_IndirectObjectHolder * pDoc,uint32_t objnum)15 CPDF_Reference::CPDF_Reference(CPDF_IndirectObjectHolder* pDoc, uint32_t objnum)
16 : m_pObjList(pDoc), m_RefObjNum(objnum) {}
17
18 CPDF_Reference::~CPDF_Reference() = default;
19
GetType() const20 CPDF_Object::Type CPDF_Reference::GetType() const {
21 return kReference;
22 }
23
GetString() const24 ByteString CPDF_Reference::GetString() const {
25 const CPDF_Object* obj = FastGetDirect();
26 return obj ? obj->GetString() : ByteString();
27 }
28
GetNumber() const29 float CPDF_Reference::GetNumber() const {
30 const CPDF_Object* obj = FastGetDirect();
31 return obj ? obj->GetNumber() : 0;
32 }
33
GetInteger() const34 int CPDF_Reference::GetInteger() const {
35 const CPDF_Object* obj = FastGetDirect();
36 return obj ? obj->GetInteger() : 0;
37 }
38
GetDictInternal() const39 const CPDF_Dictionary* CPDF_Reference::GetDictInternal() const {
40 const CPDF_Object* obj = FastGetDirect();
41 return obj ? obj->GetDictInternal() : nullptr;
42 }
43
AsMutableReference()44 CPDF_Reference* CPDF_Reference::AsMutableReference() {
45 return this;
46 }
47
Clone() const48 RetainPtr<CPDF_Object> CPDF_Reference::Clone() const {
49 return CloneObjectNonCyclic(false);
50 }
51
CloneNonCyclic(bool bDirect,std::set<const CPDF_Object * > * pVisited) const52 RetainPtr<CPDF_Object> CPDF_Reference::CloneNonCyclic(
53 bool bDirect,
54 std::set<const CPDF_Object*>* pVisited) const {
55 pVisited->insert(this);
56 if (!bDirect) {
57 return pdfium::MakeRetain<CPDF_Reference>(m_pObjList, m_RefObjNum);
58 }
59 RetainPtr<const CPDF_Object> pDirect = GetDirect();
60 return pDirect && !pdfium::Contains(*pVisited, pDirect.Get())
61 ? pDirect->CloneNonCyclic(true, pVisited)
62 : nullptr;
63 }
64
FastGetDirect() const65 const CPDF_Object* CPDF_Reference::FastGetDirect() const {
66 if (!m_pObjList)
67 return nullptr;
68 const CPDF_Object* obj =
69 m_pObjList->GetOrParseIndirectObjectInternal(m_RefObjNum);
70 return (obj && !obj->IsReference()) ? obj : nullptr;
71 }
72
SetRef(CPDF_IndirectObjectHolder * pDoc,uint32_t objnum)73 void CPDF_Reference::SetRef(CPDF_IndirectObjectHolder* pDoc, uint32_t objnum) {
74 m_pObjList = pDoc;
75 m_RefObjNum = objnum;
76 }
77
GetDirectInternal() const78 const CPDF_Object* CPDF_Reference::GetDirectInternal() const {
79 return m_pObjList ? m_pObjList->GetOrParseIndirectObjectInternal(m_RefObjNum)
80 : nullptr;
81 }
82
WriteTo(IFX_ArchiveStream * archive,const CPDF_Encryptor * encryptor) const83 bool CPDF_Reference::WriteTo(IFX_ArchiveStream* archive,
84 const CPDF_Encryptor* encryptor) const {
85 return archive->WriteString(" ") && archive->WriteDWord(GetRefObjNum()) &&
86 archive->WriteString(" 0 R ");
87 }
88
MakeReference(CPDF_IndirectObjectHolder * holder) const89 RetainPtr<CPDF_Reference> CPDF_Reference::MakeReference(
90 CPDF_IndirectObjectHolder* holder) const {
91 DCHECK_EQ(holder, m_pObjList);
92 // Do not allow reference to reference, just create other reference for same
93 // object.
94 return pdfium::MakeRetain<CPDF_Reference>(holder, GetRefObjNum());
95 }
96