• 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_DICTIONARY_H_
8 #define CORE_FPDFAPI_PARSER_CPDF_DICTIONARY_H_
9 
10 #include <map>
11 #include <memory>
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/logging.h"
23 #include "third_party/base/ptr_util.h"
24 
25 class CPDF_IndirectObjectHolder;
26 
27 class CPDF_Dictionary final : public CPDF_Object {
28  public:
29   using const_iterator =
30       std::map<ByteString, RetainPtr<CPDF_Object>>::const_iterator;
31 
32   template <typename T, typename... Args>
33   friend RetainPtr<T> pdfium::MakeRetain(Args&&... args);
34 
35   // CPDF_Object:
36   Type GetType() const override;
37   RetainPtr<CPDF_Object> Clone() const override;
38   CPDF_Dictionary* GetDict() override;
39   const CPDF_Dictionary* GetDict() const override;
40   bool IsDictionary() const override;
41   CPDF_Dictionary* AsDictionary() override;
42   const CPDF_Dictionary* AsDictionary() const override;
43   bool WriteTo(IFX_ArchiveStream* archive,
44                const CPDF_Encryptor* encryptor) const override;
45 
IsLocked()46   bool IsLocked() const { return !!m_LockCount; }
47 
size()48   size_t size() const { return m_Map.size(); }
49   const CPDF_Object* GetObjectFor(const ByteString& key) const;
50   CPDF_Object* GetObjectFor(const ByteString& key);
51   const CPDF_Object* GetDirectObjectFor(const ByteString& key) const;
52   CPDF_Object* GetDirectObjectFor(const ByteString& key);
53   ByteString GetStringFor(const ByteString& key) const;
54   ByteString GetStringFor(const ByteString& key,
55                           const ByteString& default_str) const;
56   WideString GetUnicodeTextFor(const ByteString& key) const;
57   int GetIntegerFor(const ByteString& key) const;
58   int GetIntegerFor(const ByteString& key, int default_int) const;
59   bool GetBooleanFor(const ByteString& key, bool bDefault) const;
60   float GetNumberFor(const ByteString& key) const;
61   const CPDF_Dictionary* GetDictFor(const ByteString& key) const;
62   CPDF_Dictionary* GetDictFor(const ByteString& key);
63   const CPDF_Stream* GetStreamFor(const ByteString& key) const;
64   CPDF_Stream* GetStreamFor(const ByteString& key);
65   const CPDF_Array* GetArrayFor(const ByteString& key) const;
66   CPDF_Array* GetArrayFor(const ByteString& key);
67   CFX_FloatRect GetRectFor(const ByteString& key) const;
68   CFX_Matrix GetMatrixFor(const ByteString& key) const;
GetFloatFor(const ByteString & key)69   float GetFloatFor(const ByteString& key) const { return GetNumberFor(key); }
70 
71   bool KeyExist(const ByteString& key) const;
72   std::vector<ByteString> GetKeys() const;
73 
74   // Creates a new object owned by the dictionary and returns an unowned
75   // pointer to it. Prefer using these templates over calls to SetFor(),
76   // since by creating a new object with no previous references, they ensure
77   // cycles can not be introduced.
78   template <typename T, typename... Args>
SetNewFor(const ByteString & key,Args &&...args)79   typename std::enable_if<!CanInternStrings<T>::value, T*>::type SetNewFor(
80       const ByteString& key,
81       Args&&... args) {
82     CHECK(!IsLocked());
83     return static_cast<T*>(
84         SetFor(key, pdfium::MakeRetain<T>(std::forward<Args>(args)...)));
85   }
86   template <typename T, typename... Args>
SetNewFor(const ByteString & key,Args &&...args)87   typename std::enable_if<CanInternStrings<T>::value, T*>::type SetNewFor(
88       const ByteString& key,
89       Args&&... args) {
90     CHECK(!IsLocked());
91     return static_cast<T*>(SetFor(
92         key, pdfium::MakeRetain<T>(m_pPool, std::forward<Args>(args)...)));
93   }
94 
95   // Convenience functions to convert native objects to array form.
96   void SetRectFor(const ByteString& key, const CFX_FloatRect& rect);
97   void SetMatrixFor(const ByteString& key, const CFX_Matrix& matrix);
98 
99   // Set* functions invalidate iterators for the element with the key |key|.
100   // Takes ownership of |pObj|, returns an unowned pointer to it.
101   CPDF_Object* SetFor(const ByteString& key, RetainPtr<CPDF_Object> pObj);
102 
103   void ConvertToIndirectObjectFor(const ByteString& key,
104                                   CPDF_IndirectObjectHolder* pHolder);
105 
106   // Invalidates iterators for the element with the key |key|.
107   RetainPtr<CPDF_Object> RemoveFor(const ByteString& key);
108 
109   // Invalidates iterators for the element with the key |oldkey|.
110   void ReplaceKey(const ByteString& oldkey, const ByteString& newkey);
111 
GetByteStringPool()112   WeakPtr<ByteStringPool> GetByteStringPool() const { return m_pPool; }
113 
114  private:
115   friend class CPDF_DictionaryLocker;
116 
117   CPDF_Dictionary();
118   explicit CPDF_Dictionary(const WeakPtr<ByteStringPool>& pPool);
119   ~CPDF_Dictionary() override;
120 
121   ByteString MaybeIntern(const ByteString& str);
122   RetainPtr<CPDF_Object> CloneNonCyclic(
123       bool bDirect,
124       std::set<const CPDF_Object*>* visited) const override;
125 
126   mutable uint32_t m_LockCount = 0;
127   WeakPtr<ByteStringPool> m_pPool;
128   std::map<ByteString, RetainPtr<CPDF_Object>> m_Map;
129 };
130 
131 class CPDF_DictionaryLocker {
132  public:
133   using const_iterator = CPDF_Dictionary::const_iterator;
134 
135   explicit CPDF_DictionaryLocker(const CPDF_Dictionary* pDictionary);
136   ~CPDF_DictionaryLocker();
137 
begin()138   const_iterator begin() const {
139     CHECK(m_pDictionary->IsLocked());
140     return m_pDictionary->m_Map.begin();
141   }
end()142   const_iterator end() const {
143     CHECK(m_pDictionary->IsLocked());
144     return m_pDictionary->m_Map.end();
145   }
146 
147  private:
148   RetainPtr<const CPDF_Dictionary> const m_pDictionary;
149 };
150 
ToDictionary(CPDF_Object * obj)151 inline CPDF_Dictionary* ToDictionary(CPDF_Object* obj) {
152   return obj ? obj->AsDictionary() : nullptr;
153 }
154 
ToDictionary(const CPDF_Object * obj)155 inline const CPDF_Dictionary* ToDictionary(const CPDF_Object* obj) {
156   return obj ? obj->AsDictionary() : nullptr;
157 }
158 
ToDictionary(RetainPtr<CPDF_Object> obj)159 inline RetainPtr<CPDF_Dictionary> ToDictionary(RetainPtr<CPDF_Object> obj) {
160   return RetainPtr<CPDF_Dictionary>(ToDictionary(obj.Get()));
161 }
162 
163 #endif  // CORE_FPDFAPI_PARSER_CPDF_DICTIONARY_H_
164