xref: /aosp_15_r20/external/pdfium/core/fpdfapi/parser/cpdf_dictionary.h (revision 3ac0a46f773bac49fa9476ec2b1cf3f8da5ec3a4)
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 #ifndef CORE_FPDFAPI_PARSER_CPDF_DICTIONARY_H_
8 #define CORE_FPDFAPI_PARSER_CPDF_DICTIONARY_H_
9 
10 #include <functional>
11 #include <map>
12 #include <set>
13 #include <utility>
14 #include <vector>
15 
16 #include "core/fpdfapi/parser/cpdf_object.h"
17 #include "core/fxcrt/fx_coordinates.h"
18 #include "core/fxcrt/fx_string.h"
19 #include "core/fxcrt/retain_ptr.h"
20 #include "core/fxcrt/string_pool_template.h"
21 #include "core/fxcrt/weak_ptr.h"
22 #include "third_party/base/check.h"
23 
24 class CPDF_IndirectObjectHolder;
25 
26 // Dictionaries never contain nullptr for valid keys, but some of the methods
27 // will return nullptr to indicate non-existent keys.
28 class CPDF_Dictionary final : public CPDF_Object {
29  public:
30   using DictMap = std::map<ByteString, RetainPtr<CPDF_Object>, std::less<>>;
31   using const_iterator = DictMap::const_iterator;
32 
33   CONSTRUCT_VIA_MAKE_RETAIN;
34 
35   // CPDF_Object:
36   Type GetType() const override;
37   RetainPtr<CPDF_Object> Clone() const override;
38   CPDF_Dictionary* AsMutableDictionary() override;
39   bool WriteTo(IFX_ArchiveStream* archive,
40                const CPDF_Encryptor* encryptor) const override;
41 
IsLocked()42   bool IsLocked() const { return !!m_LockCount; }
43 
size()44   size_t size() const { return m_Map.size(); }
45   RetainPtr<const CPDF_Object> GetObjectFor(const ByteString& key) const;
46   RetainPtr<CPDF_Object> GetMutableObjectFor(const ByteString& key);
47 
48   RetainPtr<const CPDF_Object> GetDirectObjectFor(const ByteString& key) const;
49   RetainPtr<CPDF_Object> GetMutableDirectObjectFor(const ByteString& key);
50 
51   // These will return the string representation of the object specified by
52   // |key|, for any object type that has a string representation.
53   ByteString GetByteStringFor(const ByteString& key) const;
54   ByteString GetByteStringFor(const ByteString& key,
55                               const ByteString& default_str) const;
56   WideString GetUnicodeTextFor(const ByteString& key) const;
57 
58   // This will only return the string representation of a name object specified
59   // by |key|. Useful when the PDF spec requires the value to be an object of
60   // type name. i.e. /Foo and not (Foo).
61   ByteString GetNameFor(const ByteString& key) const;
62 
63   bool GetBooleanFor(const ByteString& key, bool bDefault) const;
64   int GetIntegerFor(const ByteString& key) const;
65   int GetIntegerFor(const ByteString& key, int default_int) const;
66   int GetDirectIntegerFor(const ByteString& key) const;
67   float GetFloatFor(const ByteString& key) const;
68   RetainPtr<const CPDF_Dictionary> GetDictFor(const ByteString& key) const;
69   RetainPtr<CPDF_Dictionary> GetMutableDictFor(const ByteString& key);
70   RetainPtr<CPDF_Dictionary> GetOrCreateDictFor(const ByteString& key);
71   RetainPtr<const CPDF_Array> GetArrayFor(const ByteString& key) const;
72   RetainPtr<CPDF_Array> GetMutableArrayFor(const ByteString& key);
73   RetainPtr<CPDF_Array> GetOrCreateArrayFor(const ByteString& key);
74   RetainPtr<const CPDF_Stream> GetStreamFor(const ByteString& key) const;
75   RetainPtr<CPDF_Stream> GetMutableStreamFor(const ByteString& key);
76   RetainPtr<const CPDF_Number> GetNumberFor(const ByteString& key) const;
77   RetainPtr<const CPDF_String> GetStringFor(const ByteString& key) const;
78   CFX_FloatRect GetRectFor(const ByteString& key) const;
79   CFX_Matrix GetMatrixFor(const ByteString& key) const;
80 
81   bool KeyExist(const ByteString& key) const;
82   std::vector<ByteString> GetKeys() const;
83 
84   // Creates a new object owned by the dictionary and returns an unowned
85   // pointer to it. Invalidates iterators for the element with the key |key|.
86   // Prefer using these templates over calls to SetFor(), since by creating
87   // a new object with no previous references, they ensure cycles can not be
88   // introduced.
89   template <typename T, typename... Args>
90   typename std::enable_if<!CanInternStrings<T>::value, RetainPtr<T>>::type
SetNewFor(const ByteString & key,Args &&...args)91   SetNewFor(const ByteString& key, Args&&... args) {
92     return pdfium::WrapRetain(static_cast<T*>(SetForInternal(
93         key, pdfium::MakeRetain<T>(std::forward<Args>(args)...))));
94   }
95   template <typename T, typename... Args>
96   typename std::enable_if<CanInternStrings<T>::value, RetainPtr<T>>::type
SetNewFor(const ByteString & key,Args &&...args)97   SetNewFor(const ByteString& key, Args&&... args) {
98     return pdfium::WrapRetain(static_cast<T*>(SetForInternal(
99         key, pdfium::MakeRetain<T>(m_pPool, std::forward<Args>(args)...))));
100   }
101 
102   // If |pObj| is null, then |key| is erased from the map. Otherwise, takes
103   // ownership of |pObj| and stores in in the map. Invalidates iterators for
104   // the element with the key |key|.
105   void SetFor(const ByteString& key, RetainPtr<CPDF_Object> pObj);
106 
107   // Convenience functions to convert native objects to array form.
108   void SetRectFor(const ByteString& key, const CFX_FloatRect& rect);
109   void SetMatrixFor(const ByteString& key, const CFX_Matrix& matrix);
110 
111   void ConvertToIndirectObjectFor(const ByteString& key,
112                                   CPDF_IndirectObjectHolder* pHolder);
113 
114   // Invalidates iterators for the element with the key |key|.
115   RetainPtr<CPDF_Object> RemoveFor(ByteStringView key);
116 
117   // Invalidates iterators for the element with the key |oldkey|.
118   void ReplaceKey(const ByteString& oldkey, const ByteString& newkey);
119 
GetByteStringPool()120   WeakPtr<ByteStringPool> GetByteStringPool() const { return m_pPool; }
121 
122  private:
123   friend class CPDF_DictionaryLocker;
124 
125   CPDF_Dictionary();
126   explicit CPDF_Dictionary(const WeakPtr<ByteStringPool>& pPool);
127   ~CPDF_Dictionary() override;
128 
129   // No guarantees about result lifetime, use with caution.
130   const CPDF_Object* GetObjectForInternal(const ByteString& key) const;
131   const CPDF_Object* GetDirectObjectForInternal(const ByteString& key) const;
132   const CPDF_Array* GetArrayForInternal(const ByteString& key) const;
133   const CPDF_Dictionary* GetDictForInternal(const ByteString& key) const;
134   const CPDF_Number* GetNumberForInternal(const ByteString& key) const;
135   const CPDF_Stream* GetStreamForInternal(const ByteString& key) const;
136   const CPDF_String* GetStringForInternal(const ByteString& key) const;
137   CPDF_Object* SetForInternal(const ByteString& key,
138                               RetainPtr<CPDF_Object> pObj);
139 
140   ByteString MaybeIntern(const ByteString& str);
141   const CPDF_Dictionary* GetDictInternal() const override;
142   RetainPtr<CPDF_Object> CloneNonCyclic(
143       bool bDirect,
144       std::set<const CPDF_Object*>* visited) const override;
145 
146   mutable uint32_t m_LockCount = 0;
147   WeakPtr<ByteStringPool> m_pPool;
148   DictMap m_Map;
149 };
150 
151 class CPDF_DictionaryLocker {
152  public:
153   FX_STACK_ALLOCATED();
154   using const_iterator = CPDF_Dictionary::const_iterator;
155 
156   explicit CPDF_DictionaryLocker(const CPDF_Dictionary* pDictionary);
157   explicit CPDF_DictionaryLocker(RetainPtr<CPDF_Dictionary> pDictionary);
158   explicit CPDF_DictionaryLocker(RetainPtr<const CPDF_Dictionary> pDictionary);
159   ~CPDF_DictionaryLocker();
160 
begin()161   const_iterator begin() const {
162     CHECK(m_pDictionary->IsLocked());
163     return m_pDictionary->m_Map.begin();
164   }
end()165   const_iterator end() const {
166     CHECK(m_pDictionary->IsLocked());
167     return m_pDictionary->m_Map.end();
168   }
169 
170  private:
171   RetainPtr<const CPDF_Dictionary> const m_pDictionary;
172 };
173 
ToDictionary(CPDF_Object * obj)174 inline CPDF_Dictionary* ToDictionary(CPDF_Object* obj) {
175   return obj ? obj->AsMutableDictionary() : nullptr;
176 }
177 
ToDictionary(const CPDF_Object * obj)178 inline const CPDF_Dictionary* ToDictionary(const CPDF_Object* obj) {
179   return obj ? obj->AsDictionary() : nullptr;
180 }
181 
ToDictionary(RetainPtr<CPDF_Object> obj)182 inline RetainPtr<CPDF_Dictionary> ToDictionary(RetainPtr<CPDF_Object> obj) {
183   return RetainPtr<CPDF_Dictionary>(ToDictionary(obj.Get()));
184 }
185 
ToDictionary(RetainPtr<const CPDF_Object> obj)186 inline RetainPtr<const CPDF_Dictionary> ToDictionary(
187     RetainPtr<const CPDF_Object> obj) {
188   return RetainPtr<const CPDF_Dictionary>(ToDictionary(obj.Get()));
189 }
190 
191 #endif  // CORE_FPDFAPI_PARSER_CPDF_DICTIONARY_H_
192