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