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_basic.h"
19 #include "core/fxcrt/fx_coordinates.h"
20 #include "third_party/base/ptr_util.h"
21 
22 class CPDF_Array : public CPDF_Object {
23  public:
24   using const_iterator =
25       std::vector<std::unique_ptr<CPDF_Object>>::const_iterator;
26 
27   CPDF_Array();
28   explicit CPDF_Array(const CFX_WeakPtr<CFX_ByteStringPool>& pPool);
29   ~CPDF_Array() override;
30 
31   // CPDF_Object:
32   Type GetType() const override;
33   std::unique_ptr<CPDF_Object> Clone() const override;
34   bool IsArray() const override;
35   CPDF_Array* AsArray() override;
36   const CPDF_Array* AsArray() const override;
37 
IsEmpty()38   bool IsEmpty() const { return m_Objects.empty(); }
GetCount()39   size_t GetCount() const { return m_Objects.size(); }
40   CPDF_Object* GetObjectAt(size_t index) const;
41   CPDF_Object* GetDirectObjectAt(size_t index) const;
42   CFX_ByteString GetStringAt(size_t index) const;
43   int GetIntegerAt(size_t index) const;
44   FX_FLOAT GetNumberAt(size_t index) const;
45   CPDF_Dictionary* GetDictAt(size_t index) const;
46   CPDF_Stream* GetStreamAt(size_t index) const;
47   CPDF_Array* GetArrayAt(size_t index) const;
GetFloatAt(size_t index)48   FX_FLOAT GetFloatAt(size_t index) const { return GetNumberAt(index); }
49   CFX_Matrix GetMatrix();
50   CFX_FloatRect GetRect();
51 
52   // Takes ownership of |pObj|, returns unowned pointer to it.
53   CPDF_Object* Add(std::unique_ptr<CPDF_Object> pObj);
54   CPDF_Object* SetAt(size_t index, std::unique_ptr<CPDF_Object> pObj);
55   CPDF_Object* InsertAt(size_t index, std::unique_ptr<CPDF_Object> pObj);
56 
57   // Creates object owned by the array, returns unowned pointer to it.
58   // We have special cases for objects that can intern strings from
59   // a ByteStringPool.
60   template <typename T, typename... Args>
AddNew(Args &&...args)61   typename std::enable_if<!CanInternStrings<T>::value, T*>::type AddNew(
62       Args&&... args) {
63     return static_cast<T*>(
64         Add(pdfium::MakeUnique<T>(std::forward<Args>(args)...)));
65   }
66   template <typename T, typename... Args>
AddNew(Args &&...args)67   typename std::enable_if<CanInternStrings<T>::value, T*>::type AddNew(
68       Args&&... args) {
69     return static_cast<T*>(
70         Add(pdfium::MakeUnique<T>(m_pPool, std::forward<Args>(args)...)));
71   }
72   template <typename T, typename... Args>
SetNewAt(size_t index,Args &&...args)73   typename std::enable_if<!CanInternStrings<T>::value, T*>::type SetNewAt(
74       size_t index,
75       Args&&... args) {
76     return static_cast<T*>(
77         SetAt(index, pdfium::MakeUnique<T>(std::forward<Args>(args)...)));
78   }
79   template <typename T, typename... Args>
SetNewAt(size_t index,Args &&...args)80   typename std::enable_if<CanInternStrings<T>::value, T*>::type SetNewAt(
81       size_t index,
82       Args&&... args) {
83     return static_cast<T*>(SetAt(
84         index, pdfium::MakeUnique<T>(m_pPool, std::forward<Args>(args)...)));
85   }
86   template <typename T, typename... Args>
InsertNewAt(size_t index,Args &&...args)87   typename std::enable_if<!CanInternStrings<T>::value, T*>::type InsertNewAt(
88       size_t index,
89       Args&&... args) {
90     return static_cast<T*>(
91         InsertAt(index, pdfium::MakeUnique<T>(std::forward<Args>(args)...)));
92   }
93   template <typename T, typename... Args>
InsertNewAt(size_t index,Args &&...args)94   typename std::enable_if<CanInternStrings<T>::value, T*>::type InsertNewAt(
95       size_t index,
96       Args&&... args) {
97     return static_cast<T*>(InsertAt(
98         index, pdfium::MakeUnique<T>(m_pPool, std::forward<Args>(args)...)));
99   }
100 
101   void RemoveAt(size_t index, size_t nCount = 1);
102   void ConvertToIndirectObjectAt(size_t index, CPDF_IndirectObjectHolder* pDoc);
103 
begin()104   const_iterator begin() const { return m_Objects.begin(); }
end()105   const_iterator end() const { return m_Objects.end(); }
106 
107  protected:
108   std::unique_ptr<CPDF_Object> CloneNonCyclic(
109       bool bDirect,
110       std::set<const CPDF_Object*>* pVisited) const override;
111 
112   std::vector<std::unique_ptr<CPDF_Object>> m_Objects;
113   CFX_WeakPtr<CFX_ByteStringPool> m_pPool;
114 };
115 
ToArray(CPDF_Object * obj)116 inline CPDF_Array* ToArray(CPDF_Object* obj) {
117   return obj ? obj->AsArray() : nullptr;
118 }
119 
ToArray(const CPDF_Object * obj)120 inline const CPDF_Array* ToArray(const CPDF_Object* obj) {
121   return obj ? obj->AsArray() : nullptr;
122 }
123 
ToArray(std::unique_ptr<CPDF_Object> obj)124 inline std::unique_ptr<CPDF_Array> ToArray(std::unique_ptr<CPDF_Object> obj) {
125   CPDF_Array* pArray = ToArray(obj.get());
126   if (!pArray)
127     return nullptr;
128   obj.release();
129   return std::unique_ptr<CPDF_Array>(pArray);
130 }
131 
132 #endif  // CORE_FPDFAPI_PARSER_CPDF_ARRAY_H_
133