1 // Copyright 2016 PDFium Authors. All rights reserved.
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 #ifndef CORE_FPDFAPI_PARSER_CPDF_ARRAY_H_
8 #define CORE_FPDFAPI_PARSER_CPDF_ARRAY_H_
9
10 #include <memory>
11 #include <set>
12 #include <type_traits>
13 #include <utility>
14 #include <vector>
15
16 #include "core/fpdfapi/parser/cpdf_indirect_object_holder.h"
17 #include "core/fpdfapi/parser/cpdf_object.h"
18 #include "core/fxcrt/fx_coordinates.h"
19 #include "core/fxcrt/retain_ptr.h"
20 #include "third_party/base/ptr_util.h"
21
22 class CPDF_Array final : public CPDF_Object {
23 public:
24 using const_iterator = std::vector<RetainPtr<CPDF_Object>>::const_iterator;
25
26 template <typename T, typename... Args>
27 friend RetainPtr<T> pdfium::MakeRetain(Args&&... args);
28
29 // CPDF_Object:
30 Type GetType() const override;
31 RetainPtr<CPDF_Object> Clone() const override;
32 bool IsArray() const override;
33 CPDF_Array* AsArray() override;
34 const CPDF_Array* AsArray() const override;
35 bool WriteTo(IFX_ArchiveStream* archive,
36 const CPDF_Encryptor* encryptor) const override;
37
IsEmpty()38 bool IsEmpty() const { return m_Objects.empty(); }
size()39 size_t size() const { return m_Objects.size(); }
40 CPDF_Object* GetObjectAt(size_t index);
41 const CPDF_Object* GetObjectAt(size_t index) const;
42 CPDF_Object* GetDirectObjectAt(size_t index);
43 const CPDF_Object* GetDirectObjectAt(size_t index) const;
44 ByteString GetStringAt(size_t index) const;
45 WideString GetUnicodeTextAt(size_t index) const;
46 bool GetBooleanAt(size_t index, bool bDefault) const;
47 int GetIntegerAt(size_t index) const;
48 float GetNumberAt(size_t index) const;
49 CPDF_Dictionary* GetDictAt(size_t index);
50 const CPDF_Dictionary* GetDictAt(size_t index) const;
51 CPDF_Stream* GetStreamAt(size_t index);
52 const CPDF_Stream* GetStreamAt(size_t index) const;
53 CPDF_Array* GetArrayAt(size_t index);
54 const CPDF_Array* GetArrayAt(size_t index) const;
55 CFX_Matrix GetMatrix() const;
56 CFX_FloatRect GetRect() const;
57
58 // Creates object owned by the array, returns unowned pointer to it.
59 // We have special cases for objects that can intern strings from
60 // a ByteStringPool. Prefer using these templates over direct calls
61 // to Add()/SetAt()/InsertAt() since by creating a new object with no
62 // previous references, they ensure cycles can not be introduced.
63 template <typename T, typename... Args>
AddNew(Args &&...args)64 typename std::enable_if<!CanInternStrings<T>::value, T*>::type AddNew(
65 Args&&... args) {
66 return static_cast<T*>(
67 Add(pdfium::MakeRetain<T>(std::forward<Args>(args)...)));
68 }
69 template <typename T, typename... Args>
AddNew(Args &&...args)70 typename std::enable_if<CanInternStrings<T>::value, T*>::type AddNew(
71 Args&&... args) {
72 return static_cast<T*>(
73 Add(pdfium::MakeRetain<T>(m_pPool, std::forward<Args>(args)...)));
74 }
75 template <typename T, typename... Args>
SetNewAt(size_t index,Args &&...args)76 typename std::enable_if<!CanInternStrings<T>::value, T*>::type SetNewAt(
77 size_t index,
78 Args&&... args) {
79 return static_cast<T*>(
80 SetAt(index, pdfium::MakeRetain<T>(std::forward<Args>(args)...)));
81 }
82 template <typename T, typename... Args>
SetNewAt(size_t index,Args &&...args)83 typename std::enable_if<CanInternStrings<T>::value, T*>::type SetNewAt(
84 size_t index,
85 Args&&... args) {
86 return static_cast<T*>(SetAt(
87 index, pdfium::MakeRetain<T>(m_pPool, std::forward<Args>(args)...)));
88 }
89 template <typename T, typename... Args>
InsertNewAt(size_t index,Args &&...args)90 typename std::enable_if<!CanInternStrings<T>::value, T*>::type InsertNewAt(
91 size_t index,
92 Args&&... args) {
93 return static_cast<T*>(
94 InsertAt(index, pdfium::MakeRetain<T>(std::forward<Args>(args)...)));
95 }
96 template <typename T, typename... Args>
InsertNewAt(size_t index,Args &&...args)97 typename std::enable_if<CanInternStrings<T>::value, T*>::type InsertNewAt(
98 size_t index,
99 Args&&... args) {
100 return static_cast<T*>(InsertAt(
101 index, pdfium::MakeRetain<T>(m_pPool, std::forward<Args>(args)...)));
102 }
103
104 // Takes ownership of |pObj|, returns unowned pointer to it.
105 CPDF_Object* Add(RetainPtr<CPDF_Object> pObj);
106 CPDF_Object* SetAt(size_t index, RetainPtr<CPDF_Object> pObj);
107 CPDF_Object* InsertAt(size_t index, RetainPtr<CPDF_Object> pObj);
108
109 void Clear();
110 void RemoveAt(size_t index);
111 void ConvertToIndirectObjectAt(size_t index,
112 CPDF_IndirectObjectHolder* pHolder);
IsLocked()113 bool IsLocked() const { return !!m_LockCount; }
114
115 private:
116 friend class CPDF_ArrayLocker;
117
118 CPDF_Array();
119 explicit CPDF_Array(const WeakPtr<ByteStringPool>& pPool);
120 ~CPDF_Array() override;
121
122 RetainPtr<CPDF_Object> CloneNonCyclic(
123 bool bDirect,
124 std::set<const CPDF_Object*>* pVisited) const override;
125
126 std::vector<RetainPtr<CPDF_Object>> m_Objects;
127 WeakPtr<ByteStringPool> m_pPool;
128 mutable uint32_t m_LockCount = 0;
129 };
130
131 class CPDF_ArrayLocker {
132 public:
133 using const_iterator = CPDF_Array::const_iterator;
134
135 explicit CPDF_ArrayLocker(const CPDF_Array* pArray);
136 ~CPDF_ArrayLocker();
137
begin()138 const_iterator begin() const {
139 CHECK(m_pArray->IsLocked());
140 return m_pArray->m_Objects.begin();
141 }
end()142 const_iterator end() const {
143 CHECK(m_pArray->IsLocked());
144 return m_pArray->m_Objects.end();
145 }
146
147 private:
148 RetainPtr<const CPDF_Array> const m_pArray;
149 };
150
ToArray(CPDF_Object * obj)151 inline CPDF_Array* ToArray(CPDF_Object* obj) {
152 return obj ? obj->AsArray() : nullptr;
153 }
154
ToArray(const CPDF_Object * obj)155 inline const CPDF_Array* ToArray(const CPDF_Object* obj) {
156 return obj ? obj->AsArray() : nullptr;
157 }
158
ToArray(RetainPtr<CPDF_Object> obj)159 inline RetainPtr<CPDF_Array> ToArray(RetainPtr<CPDF_Object> obj) {
160 return RetainPtr<CPDF_Array>(ToArray(obj.Get()));
161 }
162
163 #endif // CORE_FPDFAPI_PARSER_CPDF_ARRAY_H_
164