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 "third_party/base/ptr_util.h"
20
21 class CPDF_Array : public CPDF_Object {
22 public:
23 using const_iterator =
24 std::vector<std::unique_ptr<CPDF_Object>>::const_iterator;
25
26 CPDF_Array();
27 explicit CPDF_Array(const WeakPtr<ByteStringPool>& pPool);
28 ~CPDF_Array() override;
29
30 // CPDF_Object:
31 Type GetType() const override;
32 std::unique_ptr<CPDF_Object> Clone() const override;
33 bool IsArray() const override;
34 CPDF_Array* AsArray() override;
35 const CPDF_Array* AsArray() const override;
36 bool WriteTo(IFX_ArchiveStream* archive) 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 ByteString GetStringAt(size_t index) const;
43 WideString GetUnicodeTextAt(size_t index) const;
44 int GetIntegerAt(size_t index) const;
45 float GetNumberAt(size_t index) const;
46 CPDF_Dictionary* GetDictAt(size_t index) const;
47 CPDF_Stream* GetStreamAt(size_t index) const;
48 CPDF_Array* GetArrayAt(size_t index) const;
GetFloatAt(size_t index)49 float GetFloatAt(size_t index) const { return GetNumberAt(index); }
50 CFX_Matrix GetMatrix();
51 CFX_FloatRect GetRect();
52
53 // Takes ownership of |pObj|, returns unowned pointer to it.
54 CPDF_Object* Add(std::unique_ptr<CPDF_Object> pObj);
55 CPDF_Object* SetAt(size_t index, std::unique_ptr<CPDF_Object> pObj);
56 CPDF_Object* InsertAt(size_t index, std::unique_ptr<CPDF_Object> pObj);
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.
61 template <typename T, typename... Args>
AddNew(Args &&...args)62 typename std::enable_if<!CanInternStrings<T>::value, T*>::type AddNew(
63 Args&&... args) {
64 return static_cast<T*>(
65 Add(pdfium::MakeUnique<T>(std::forward<Args>(args)...)));
66 }
67 template <typename T, typename... Args>
AddNew(Args &&...args)68 typename std::enable_if<CanInternStrings<T>::value, T*>::type AddNew(
69 Args&&... args) {
70 return static_cast<T*>(
71 Add(pdfium::MakeUnique<T>(m_pPool, std::forward<Args>(args)...)));
72 }
73 template <typename T, typename... Args>
SetNewAt(size_t index,Args &&...args)74 typename std::enable_if<!CanInternStrings<T>::value, T*>::type SetNewAt(
75 size_t index,
76 Args&&... args) {
77 return static_cast<T*>(
78 SetAt(index, pdfium::MakeUnique<T>(std::forward<Args>(args)...)));
79 }
80 template <typename T, typename... Args>
SetNewAt(size_t index,Args &&...args)81 typename std::enable_if<CanInternStrings<T>::value, T*>::type SetNewAt(
82 size_t index,
83 Args&&... args) {
84 return static_cast<T*>(SetAt(
85 index, pdfium::MakeUnique<T>(m_pPool, std::forward<Args>(args)...)));
86 }
87 template <typename T, typename... Args>
InsertNewAt(size_t index,Args &&...args)88 typename std::enable_if<!CanInternStrings<T>::value, T*>::type InsertNewAt(
89 size_t index,
90 Args&&... args) {
91 return static_cast<T*>(
92 InsertAt(index, pdfium::MakeUnique<T>(std::forward<Args>(args)...)));
93 }
94 template <typename T, typename... Args>
InsertNewAt(size_t index,Args &&...args)95 typename std::enable_if<CanInternStrings<T>::value, T*>::type InsertNewAt(
96 size_t index,
97 Args&&... args) {
98 return static_cast<T*>(InsertAt(
99 index, pdfium::MakeUnique<T>(m_pPool, std::forward<Args>(args)...)));
100 }
101
102 void Clear();
103 void RemoveAt(size_t index);
104 void ConvertToIndirectObjectAt(size_t index, CPDF_IndirectObjectHolder* pDoc);
105
begin()106 const_iterator begin() const { return m_Objects.begin(); }
end()107 const_iterator end() const { return m_Objects.end(); }
108
109 protected:
110 std::unique_ptr<CPDF_Object> CloneNonCyclic(
111 bool bDirect,
112 std::set<const CPDF_Object*>* pVisited) const override;
113
114 std::vector<std::unique_ptr<CPDF_Object>> m_Objects;
115 WeakPtr<ByteStringPool> m_pPool;
116 };
117
ToArray(CPDF_Object * obj)118 inline CPDF_Array* ToArray(CPDF_Object* obj) {
119 return obj ? obj->AsArray() : nullptr;
120 }
121
ToArray(const CPDF_Object * obj)122 inline const CPDF_Array* ToArray(const CPDF_Object* obj) {
123 return obj ? obj->AsArray() : nullptr;
124 }
125
ToArray(std::unique_ptr<CPDF_Object> obj)126 inline std::unique_ptr<CPDF_Array> ToArray(std::unique_ptr<CPDF_Object> obj) {
127 CPDF_Array* pArray = ToArray(obj.get());
128 if (!pArray)
129 return nullptr;
130 obj.release();
131 return std::unique_ptr<CPDF_Array>(pArray);
132 }
133
134 #endif // CORE_FPDFAPI_PARSER_CPDF_ARRAY_H_
135