1 | //======================================================================== |
2 | // |
3 | // Dict.h |
4 | // |
5 | // Copyright 1996-2003 Glyph & Cog, LLC |
6 | // |
7 | //======================================================================== |
8 | |
9 | //======================================================================== |
10 | // |
11 | // Modified under the Poppler project - http://poppler.freedesktop.org |
12 | // |
13 | // All changes made under the Poppler project to this file are licensed |
14 | // under GPL version 2 or later |
15 | // |
16 | // Copyright (C) 2005 Kristian Høgsberg <krh@redhat.com> |
17 | // Copyright (C) 2006 Krzysztof Kowalczyk <kkowalczyk@gmail.com> |
18 | // Copyright (C) 2007-2008 Julien Rebetez <julienr@svn.gnome.org> |
19 | // Copyright (C) 2010, 2017-2022 Albert Astals Cid <aacid@kde.org> |
20 | // Copyright (C) 2010 Paweł Wiejacha <pawel.wiejacha@gmail.com> |
21 | // Copyright (C) 2013 Thomas Freitag <Thomas.Freitag@alfa.de> |
22 | // Copyright (C) 2017 Adrian Johnson <ajohnson@redneon.com> |
23 | // Copyright (C) 2018 Adam Reichold <adam.reichold@t-online.de> |
24 | // |
25 | // To see a description of the changes please see the Changelog file that |
26 | // came with your tarball or type make ChangeLog if you are building from git |
27 | // |
28 | //======================================================================== |
29 | |
30 | #ifndef DICT_H |
31 | #define DICT_H |
32 | |
33 | #include <atomic> |
34 | #include <mutex> |
35 | #include <string> |
36 | #include <vector> |
37 | #include <utility> |
38 | |
39 | #include "poppler-config.h" |
40 | #include "poppler_private_export.h" |
41 | #include "Object.h" |
42 | |
43 | //------------------------------------------------------------------------ |
44 | // Dict |
45 | //------------------------------------------------------------------------ |
46 | |
47 | class POPPLER_PRIVATE_EXPORT Dict |
48 | { |
49 | public: |
50 | // Constructor. |
51 | explicit Dict(XRef *xrefA); |
52 | explicit Dict(const Dict *dictA); |
53 | Dict *copy(XRef *xrefA) const; |
54 | |
55 | Dict *deepCopy() const; |
56 | |
57 | Dict(const Dict &) = delete; |
58 | Dict &operator=(const Dict &) = delete; |
59 | |
60 | // Get number of entries. |
61 | int getLength() const { return static_cast<int>(entries.size()); } |
62 | |
63 | // Add an entry. (Copies key into Dict.) |
64 | // val becomes a dead object after the call |
65 | void add(const char *key, Object &&val); |
66 | |
67 | // Add an entry. (Takes ownership of key.) |
68 | void add(char *key, Object &&val) = delete; |
69 | |
70 | // Update the value of an existing entry, otherwise create it |
71 | // val becomes a dead object after the call |
72 | void set(const char *key, Object &&val); |
73 | // Remove an entry. This invalidate indexes |
74 | void remove(const char *key); |
75 | |
76 | // Check if dictionary is of specified type. |
77 | bool is(const char *type) const; |
78 | |
79 | // Look up an entry and return the value. Returns a null object |
80 | // if <key> is not in the dictionary. |
81 | Object lookup(const char *key, int recursion = 0) const; |
82 | // Same as above but if the returned object is a fetched Ref returns such Ref in returnRef, otherwise returnRef is Ref::INVALID() |
83 | Object lookup(const char *key, Ref *returnRef, int recursion = 0) const; |
84 | // Look up an entry and return the value. Returns a null object |
85 | // if <key> is not in the dictionary or if it is a ref to a non encrypted object in a partially encrypted document |
86 | Object lookupEnsureEncryptedIfNeeded(const char *key) const; |
87 | const Object &lookupNF(const char *key) const; |
88 | bool lookupInt(const char *key, const char *alt_key, int *value) const; |
89 | |
90 | // Iterative accessors. |
91 | const char *getKey(int i) const { return entries[i].first.c_str(); } |
92 | Object getVal(int i) const { return entries[i].second.fetch(xref); } |
93 | // Same as above but if the returned object is a fetched Ref returns such Ref in returnRef, otherwise returnRef is Ref::INVALID() |
94 | Object getVal(int i, Ref *returnRef) const; |
95 | const Object &getValNF(int i) const { return entries[i].second; } |
96 | |
97 | // Set the xref pointer. This is only used in one special case: the |
98 | // trailer dictionary, which is read before the xref table is |
99 | // parsed. |
100 | void setXRef(XRef *xrefA) { xref = xrefA; } |
101 | |
102 | XRef *getXRef() const { return xref; } |
103 | |
104 | bool hasKey(const char *key) const; |
105 | |
106 | // Returns a key name that is not in the dictionary |
107 | // It will be suggestedKey itself if available |
108 | // otherwise it will start adding 0, 1, 2, 3, etc. to suggestedKey until there's one available |
109 | std::string findAvailableKey(const std::string &suggestedKey); |
110 | |
111 | private: |
112 | friend class Object; // for incRef/decRef |
113 | |
114 | // Reference counting. |
115 | int incRef() { return ++ref; } |
116 | int decRef() { return --ref; } |
117 | |
118 | using DictEntry = std::pair<std::string, Object>; |
119 | struct CmpDictEntry; |
120 | |
121 | XRef *xref; // the xref table for this PDF file |
122 | std::vector<DictEntry> entries; |
123 | std::atomic_int ref; // reference count |
124 | std::atomic_bool sorted; |
125 | mutable std::recursive_mutex mutex; |
126 | |
127 | const DictEntry *find(const char *key) const; |
128 | DictEntry *find(const char *key); |
129 | }; |
130 | |
131 | #endif |
132 | |