• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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