1 //========================================================================
5 // Copyright 1996-2003 Glyph & Cog, LLC
7 //========================================================================
9 //========================================================================
11 // Modified under the Poppler project - http://poppler.freedesktop.org
13 // All changes made under the Poppler project to this file are licensed
14 // under GPL version 2 or later
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) 2008, 2010, 2013, 2014 Albert Astals Cid <aacid@kde.org>
20 // Copyright (C) 2010 Paweł Wiejacha <pawel.wiejacha@gmail.com>
21 // Copyright (C) 2012 Fabio D'Urso <fabiodurso@hotmail.it>
22 // Copyright (C) 2013 Thomas Freitag <Thomas.Freitag@alfa.de>
23 // Copyright (C) 2014 Scott West <scott.gregory.west@gmail.com>
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
28 //========================================================================
32 #ifdef USE_GCC_PRAGMAS
33 #pragma implementation
45 # define dictLocker() MutexLocker locker(&mutex)
49 //------------------------------------------------------------------------
51 //------------------------------------------------------------------------
53 static const int SORT_LENGTH_LOWER_LIMIT
= 32;
55 static inline bool cmpDictEntries(const DictEntry
&e1
, const DictEntry
&e2
)
57 return strcmp(e1
.key
, e2
.key
) < 0;
60 static int binarySearch(const char *key
, DictEntry
*entries
, int length
)
64 while (first
<= end
) {
65 const int middle
= (first
+ end
) / 2;
66 const int res
= strcmp(key
, entries
[middle
].key
);
78 Dict::Dict(XRef
*xrefA
) {
89 Dict::Dict(Dict
* dictA
) {
91 size
= length
= dictA
->length
;
97 sorted
= dictA
->sorted
;
98 entries
= (DictEntry
*)gmallocn(size
, sizeof(DictEntry
));
99 for (int i
=0; i
<length
; i
++) {
100 entries
[i
].key
= copyString(dictA
->entries
[i
].key
);
101 dictA
->entries
[i
].val
.copy(&entries
[i
].val
);
105 Dict
*Dict::copy(XRef
*xrefA
) {
107 Dict
*dictA
= new Dict(this);
109 for (int i
=0; i
<length
; i
++) {
110 if (dictA
->entries
[i
].val
.getType() == objDict
) {
111 Dict
*dict
= dictA
->entries
[i
].val
.getDict();
113 obj
.initDict(dict
->copy(xrefA
));
114 dictA
->entries
[i
].val
.free();
115 dictA
->entries
[i
].val
= obj
;
125 for (i
= 0; i
< length
; ++i
) {
126 gfree(entries
[i
].key
);
127 entries
[i
].val
.free();
131 gDestroyMutex(&mutex
);
147 void Dict::add(char *key
, Object
*val
) {
150 // We use add on very few occasions so
151 // virtually this will never be hit
155 if (length
== size
) {
161 entries
= (DictEntry
*)greallocn(entries
, size
, sizeof(DictEntry
));
163 entries
[length
].key
= key
;
164 entries
[length
].val
= *val
;
168 inline DictEntry
*Dict::find(const char *key
) {
169 if (!sorted
&& length
>= SORT_LENGTH_LOWER_LIMIT
)
173 std::sort(entries
, entries
+length
, cmpDictEntries
);
177 const int pos
= binarySearch(key
, entries
, length
);
179 return &entries
[pos
];
184 for (i
= length
- 1; i
>=0; --i
) {
185 if (!strcmp(key
, entries
[i
].key
))
192 GBool
Dict::hasKey(const char *key
) {
193 return find(key
) != NULL
;
196 void Dict::remove(const char *key
) {
199 const int pos
= binarySearch(key
, entries
, length
);
202 gfree(entries
[pos
].key
);
203 entries
[pos
].val
.free();
205 memmove(&entries
[pos
], &entries
[pos
+ 1], (length
- pos
) * sizeof(DictEntry
));
216 for(i
=0; i
<length
; i
++) {
217 if (!strcmp(key
, entries
[i
].key
)) {
225 //replace the deleted entry with the last entry
226 gfree(entries
[i
].key
);
227 entries
[i
].val
.free();
229 tmp
= entries
[length
];
230 if (i
!=length
) //don't copy the last entry if it is deleted
235 void Dict::set(const char *key
, Object
*val
) {
247 add (copyString(key
), val
);
252 GBool
Dict::is(const char *type
) {
255 return (e
= find("Type")) && e
->val
.isName(type
);
258 Object
*Dict::lookup(const char *key
, Object
*obj
, int recursion
) {
261 return (e
= find(key
)) ? e
->val
.fetch(xref
, obj
, recursion
) : obj
->initNull();
264 Object
*Dict::lookupNF(const char *key
, Object
*obj
) {
267 return (e
= find(key
)) ? e
->val
.copy(obj
) : obj
->initNull();
270 GBool
Dict::lookupInt(const char *key
, const char *alt_key
, int *value
)
273 GBool success
= gFalse
;
275 lookup ((char *) key
, &obj1
);
276 if (obj1
.isNull () && alt_key
!= NULL
) {
278 lookup ((char *) alt_key
, &obj1
);
281 *value
= obj1
.getInt ();
290 char *Dict::getKey(int i
) {
291 return entries
[i
].key
;
294 Object
*Dict::getVal(int i
, Object
*obj
) {
295 return entries
[i
].val
.fetch(xref
, obj
);
298 Object
*Dict::getValNF(int i
, Object
*obj
) {
299 return entries
[i
].val
.copy(obj
);