Remove void* ctor from CPDF_Number.
[pdfium.git] / core / src / fpdfapi / fpdf_parser / fpdf_parser_objects.cpp
1 // Copyright 2014 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 #include "../../../include/fpdfapi/fpdf_parser.h"
8 #include "../../../include/fxcrt/fx_string.h"
9
10 // static
11 int CPDF_Object::s_nCurRefDepth = 0;
12
13 void CPDF_Object::Release() {
14   if (m_ObjNum) {
15     return;
16   }
17   Destroy();
18 }
19 void CPDF_Object::Destroy() {
20   switch (m_Type) {
21     case PDFOBJ_STRING:
22       delete (CPDF_String*)this;
23       break;
24     case PDFOBJ_NAME:
25       delete (CPDF_Name*)this;
26       break;
27     case PDFOBJ_ARRAY:
28       delete (CPDF_Array*)this;
29       break;
30     case PDFOBJ_DICTIONARY:
31       delete this->AsDictionary();
32       break;
33     case PDFOBJ_STREAM:
34       delete (CPDF_Stream*)this;
35       break;
36     default:
37       delete this;
38   }
39 }
40 CFX_ByteString CPDF_Object::GetString() const {
41   switch (m_Type) {
42     case PDFOBJ_BOOLEAN:
43       return AsBoolean()->m_bValue ? "true" : "false";
44     case PDFOBJ_NUMBER:
45       return ((CPDF_Number*)this)->GetString();
46     case PDFOBJ_STRING:
47       return ((CPDF_String*)this)->m_String;
48     case PDFOBJ_NAME:
49       return ((CPDF_Name*)this)->m_Name;
50     case PDFOBJ_REFERENCE: {
51       CPDF_Reference* pRef = (CPDF_Reference*)(void*)this;
52       if (pRef->m_pObjList == NULL) {
53         break;
54       }
55       CPDF_Object* pObj =
56           pRef->m_pObjList->GetIndirectObject(pRef->GetRefObjNum());
57       if (pObj == NULL) {
58         return CFX_ByteString();
59       }
60       return pObj->GetString();
61     }
62   }
63   return CFX_ByteString();
64 }
65 CFX_ByteStringC CPDF_Object::GetConstString() const {
66   switch (m_Type) {
67     case PDFOBJ_STRING:
68       return CFX_ByteStringC((const uint8_t*)((CPDF_String*)this)->m_String,
69                              ((CPDF_String*)this)->m_String.GetLength());
70     case PDFOBJ_NAME:
71       return CFX_ByteStringC((const uint8_t*)((CPDF_Name*)this)->m_Name,
72                              ((CPDF_Name*)this)->m_Name.GetLength());
73     case PDFOBJ_REFERENCE: {
74       CPDF_Reference* pRef = (CPDF_Reference*)(void*)this;
75       if (pRef->m_pObjList == NULL) {
76         break;
77       }
78       CPDF_Object* pObj =
79           pRef->m_pObjList->GetIndirectObject(pRef->GetRefObjNum());
80       if (pObj == NULL) {
81         return CFX_ByteStringC();
82       }
83       return pObj->GetConstString();
84     }
85   }
86   return CFX_ByteStringC();
87 }
88 FX_FLOAT CPDF_Object::GetNumber() const {
89   switch (m_Type) {
90     case PDFOBJ_NUMBER:
91       return ((CPDF_Number*)this)->GetNumber();
92     case PDFOBJ_REFERENCE: {
93       CPDF_Reference* pRef = (CPDF_Reference*)(void*)this;
94       if (pRef->m_pObjList == NULL) {
95         break;
96       }
97       CPDF_Object* pObj =
98           pRef->m_pObjList->GetIndirectObject(pRef->GetRefObjNum());
99       if (pObj == NULL) {
100         return 0;
101       }
102       return pObj->GetNumber();
103     }
104   }
105   return 0;
106 }
107 FX_FLOAT CPDF_Object::GetNumber16() const {
108   return GetNumber();
109 }
110 int CPDF_Object::GetInteger() const {
111   CFX_AutoRestorer<int> restorer(&s_nCurRefDepth);
112   if (++s_nCurRefDepth > OBJECT_REF_MAX_DEPTH) {
113     return 0;
114   }
115   switch (m_Type) {
116     case PDFOBJ_BOOLEAN:
117       return this->AsBoolean()->m_bValue;
118     case PDFOBJ_NUMBER:
119       return ((CPDF_Number*)this)->GetInteger();
120     case PDFOBJ_REFERENCE: {
121       CPDF_Reference* pRef = (CPDF_Reference*)(void*)this;
122       PARSE_CONTEXT context;
123       FXSYS_memset(&context, 0, sizeof(PARSE_CONTEXT));
124       if (pRef->m_pObjList == NULL) {
125         return 0;
126       }
127       CPDF_Object* pObj =
128           pRef->m_pObjList->GetIndirectObject(pRef->GetRefObjNum(), &context);
129       if (pObj == NULL) {
130         return 0;
131       }
132       return pObj->GetInteger();
133     }
134   }
135   return 0;
136 }
137
138 CPDF_Dictionary* CPDF_Object::GetDict() const {
139   switch (m_Type) {
140     case PDFOBJ_DICTIONARY:
141       // The method should be made non-const if we want to not be const.
142       // See bug #234.
143       return const_cast<CPDF_Dictionary*>(this->AsDictionary());
144     case PDFOBJ_STREAM:
145       return ((CPDF_Stream*)this)->GetDict();
146     case PDFOBJ_REFERENCE: {
147       CPDF_Reference* pRef = (CPDF_Reference*)this;
148       CPDF_IndirectObjects* pIndirect = pRef->GetObjList();
149       if (!pIndirect)
150         return nullptr;
151       CPDF_Object* pObj = pIndirect->GetIndirectObject(pRef->GetRefObjNum());
152       if (!pObj || (pObj == this))
153         return nullptr;
154       return pObj->GetDict();
155     }
156     default:
157       return nullptr;
158   }
159 }
160
161 CPDF_Array* CPDF_Object::GetArray() const {
162   if (m_Type == PDFOBJ_ARRAY)
163     return (CPDF_Array*)this;
164
165   return NULL;
166 }
167 void CPDF_Object::SetString(const CFX_ByteString& str) {
168   ASSERT(this != NULL);
169   switch (m_Type) {
170     case PDFOBJ_BOOLEAN:
171       AsBoolean()->m_bValue = (str == FX_BSTRC("true"));
172       return;
173     case PDFOBJ_NUMBER:
174       ((CPDF_Number*)this)->SetString(str);
175       return;
176     case PDFOBJ_STRING:
177       ((CPDF_String*)this)->m_String = str;
178       return;
179     case PDFOBJ_NAME:
180       ((CPDF_Name*)this)->m_Name = str;
181       return;
182   }
183   ASSERT(FALSE);
184 }
185 int CPDF_Object::GetDirectType() const {
186   if (m_Type != PDFOBJ_REFERENCE) {
187     return m_Type;
188   }
189   CPDF_Reference* pRef = (CPDF_Reference*)this;
190   return pRef->m_pObjList->GetIndirectType(pRef->GetRefObjNum());
191 }
192 FX_BOOL CPDF_Object::IsIdentical(CPDF_Object* pOther) const {
193   if (this == pOther) {
194     return TRUE;
195   }
196   if (pOther == NULL) {
197     return FALSE;
198   }
199   if (pOther->m_Type != m_Type) {
200     if (m_Type == PDFOBJ_REFERENCE && GetDirect()) {
201       return GetDirect()->IsIdentical(pOther);
202     }
203     if (pOther->m_Type == PDFOBJ_REFERENCE) {
204       return IsIdentical(pOther->GetDirect());
205     }
206     return FALSE;
207   }
208   switch (m_Type) {
209     case PDFOBJ_BOOLEAN:
210       return this->AsBoolean()->Identical(pOther->AsBoolean());
211     case PDFOBJ_NUMBER:
212       return (((CPDF_Number*)this)->Identical((CPDF_Number*)pOther));
213     case PDFOBJ_STRING:
214       return (((CPDF_String*)this)->Identical((CPDF_String*)pOther));
215     case PDFOBJ_NAME:
216       return (((CPDF_Name*)this)->Identical((CPDF_Name*)pOther));
217     case PDFOBJ_ARRAY:
218       return (((CPDF_Array*)this)->Identical((CPDF_Array*)pOther));
219     case PDFOBJ_DICTIONARY:
220       return this->AsDictionary()->Identical(pOther->AsDictionary());
221     case PDFOBJ_NULL:
222       return TRUE;
223     case PDFOBJ_STREAM:
224       return (((CPDF_Stream*)this)->Identical((CPDF_Stream*)pOther));
225     case PDFOBJ_REFERENCE:
226       return (((CPDF_Reference*)this)->Identical((CPDF_Reference*)pOther));
227   }
228   return FALSE;
229 }
230 CPDF_Object* CPDF_Object::GetDirect() const {
231   if (m_Type != PDFOBJ_REFERENCE) {
232     return (CPDF_Object*)this;
233   }
234   CPDF_Reference* pRef = (CPDF_Reference*)(void*)this;
235   if (pRef->m_pObjList == NULL) {
236     return NULL;
237   }
238   return pRef->m_pObjList->GetIndirectObject(pRef->GetRefObjNum());
239 }
240 CPDF_Object* CPDF_Object::Clone(FX_BOOL bDirect) const {
241   CFX_MapPtrToPtr visited;
242   return CloneInternal(bDirect, &visited);
243 }
244 CPDF_Object* CPDF_Object::CloneInternal(FX_BOOL bDirect,
245                                         CFX_MapPtrToPtr* visited) const {
246   switch (m_Type) {
247     case PDFOBJ_BOOLEAN:
248       return new CPDF_Boolean(this->AsBoolean()->m_bValue);
249     case PDFOBJ_NUMBER:
250       if (((CPDF_Number*)this)->m_bInteger)
251         return new CPDF_Number(((CPDF_Number*)this)->m_Integer);
252       return new CPDF_Number(((CPDF_Number*)this)->m_Float);
253     case PDFOBJ_STRING:
254       return new CPDF_String(((CPDF_String*)this)->m_String,
255                              ((CPDF_String*)this)->IsHex());
256     case PDFOBJ_NAME:
257       return new CPDF_Name(((CPDF_Name*)this)->m_Name);
258     case PDFOBJ_ARRAY: {
259       CPDF_Array* pCopy = new CPDF_Array();
260       CPDF_Array* pThis = (CPDF_Array*)this;
261       int n = pThis->GetCount();
262       for (int i = 0; i < n; i++) {
263         CPDF_Object* value = (CPDF_Object*)pThis->m_Objects.GetAt(i);
264         pCopy->m_Objects.Add(value->CloneInternal(bDirect, visited));
265       }
266       return pCopy;
267     }
268     case PDFOBJ_DICTIONARY: {
269       CPDF_Dictionary* pCopy = new CPDF_Dictionary();
270       const CPDF_Dictionary* pThis = this->AsDictionary();
271       FX_POSITION pos = pThis->m_Map.GetStartPosition();
272       while (pos) {
273         CFX_ByteString key;
274         CPDF_Object* value;
275         pThis->m_Map.GetNextAssoc(pos, key, (void*&)value);
276         pCopy->m_Map.SetAt(key, value->CloneInternal(bDirect, visited));
277       }
278       return pCopy;
279     }
280     case PDFOBJ_NULL: {
281       return new CPDF_Null;
282     }
283     case PDFOBJ_STREAM: {
284       CPDF_Stream* pThis = (CPDF_Stream*)this;
285       CPDF_StreamAcc acc;
286       acc.LoadAllData(pThis, TRUE);
287       FX_DWORD streamSize = acc.GetSize();
288       CPDF_Dictionary* pDict = pThis->GetDict();
289       if (pDict) {
290         pDict = ToDictionary(pDict->CloneInternal(bDirect, visited));
291       }
292       return new CPDF_Stream(acc.DetachData(), streamSize, pDict);
293     }
294     case PDFOBJ_REFERENCE: {
295       CPDF_Reference* pRef = (CPDF_Reference*)this;
296       FX_DWORD obj_num = pRef->GetRefObjNum();
297       if (bDirect && !visited->GetValueAt((void*)(uintptr_t)obj_num)) {
298         visited->SetAt((void*)(uintptr_t)obj_num, (void*)1);
299         if (!pRef->GetDirect())
300           return nullptr;
301
302         return pRef->GetDirect()->CloneInternal(TRUE, visited);
303       }
304       return new CPDF_Reference(pRef->m_pObjList, obj_num);
305     }
306   }
307   return NULL;
308 }
309 CPDF_Object* CPDF_Object::CloneRef(CPDF_IndirectObjects* pDoc) const {
310   if (m_ObjNum) {
311     return new CPDF_Reference(pDoc, m_ObjNum);
312   }
313   return Clone();
314 }
315 CFX_WideString CPDF_Object::GetUnicodeText(CFX_CharMap* pCharMap) const {
316   if (m_Type == PDFOBJ_STRING) {
317     return PDF_DecodeText(((CPDF_String*)this)->m_String, pCharMap);
318   }
319   if (m_Type == PDFOBJ_STREAM) {
320     CPDF_StreamAcc stream;
321     stream.LoadAllData((CPDF_Stream*)this, FALSE);
322     CFX_WideString result =
323         PDF_DecodeText(stream.GetData(), stream.GetSize(), pCharMap);
324     return result;
325   }
326   if (m_Type == PDFOBJ_NAME) {
327     return PDF_DecodeText(((CPDF_Name*)this)->m_Name, pCharMap);
328   }
329   return CFX_WideString();
330 }
331 void CPDF_Object::SetUnicodeText(const FX_WCHAR* pUnicodes, int len) {
332   if (m_Type == PDFOBJ_STRING) {
333     ((CPDF_String*)this)->m_String = PDF_EncodeText(pUnicodes, len);
334   } else if (m_Type == PDFOBJ_STREAM) {
335     CFX_ByteString result = PDF_EncodeText(pUnicodes, len);
336     ((CPDF_Stream*)this)
337         ->SetData((uint8_t*)result.c_str(), result.GetLength(), FALSE, FALSE);
338   }
339 }
340
341 CPDF_Boolean* CPDF_Object::AsBoolean() {
342   return IsBoolean() ? static_cast<CPDF_Boolean*>(this) : nullptr;
343 }
344
345 const CPDF_Boolean* CPDF_Object::AsBoolean() const {
346   return IsBoolean() ? static_cast<const CPDF_Boolean*>(this) : nullptr;
347 }
348
349 CPDF_Dictionary* CPDF_Object::AsDictionary() {
350   return IsDictionary() ? static_cast<CPDF_Dictionary*>(this) : nullptr;
351 }
352
353 const CPDF_Dictionary* CPDF_Object::AsDictionary() const {
354   return IsDictionary() ? static_cast<const CPDF_Dictionary*>(this) : nullptr;
355 }
356
357 CPDF_Number::CPDF_Number(int value)
358     : CPDF_Object(PDFOBJ_NUMBER), m_bInteger(TRUE), m_Integer(value) {}
359
360 CPDF_Number::CPDF_Number(FX_FLOAT value)
361     : CPDF_Object(PDFOBJ_NUMBER), m_bInteger(FALSE), m_Float(value) {}
362
363 CPDF_Number::CPDF_Number(const CFX_ByteStringC& str)
364     : CPDF_Object(PDFOBJ_NUMBER) {
365   FX_atonum(str, m_bInteger, &m_Integer);
366 }
367
368 void CPDF_Number::SetString(const CFX_ByteStringC& str) {
369   FX_atonum(str, m_bInteger, &m_Integer);
370 }
371 FX_BOOL CPDF_Number::Identical(CPDF_Number* pOther) const {
372   return m_bInteger == pOther->m_bInteger && m_Integer == pOther->m_Integer;
373 }
374 CFX_ByteString CPDF_Number::GetString() const {
375   return m_bInteger ? CFX_ByteString::FormatInteger(m_Integer, FXFORMAT_SIGNED)
376                     : CFX_ByteString::FormatFloat(m_Float);
377 }
378 void CPDF_Number::SetNumber(FX_FLOAT value) {
379   m_bInteger = FALSE;
380   m_Float = value;
381 }
382 CPDF_String::CPDF_String(const CFX_WideString& str)
383     : CPDF_Object(PDFOBJ_STRING), m_bHex(FALSE) {
384   m_String = PDF_EncodeText(str);
385 }
386 CPDF_Array::~CPDF_Array() {
387   int size = m_Objects.GetSize();
388   CPDF_Object** pList = (CPDF_Object**)m_Objects.GetData();
389   for (int i = 0; i < size; i++) {
390     if (pList[i])
391       pList[i]->Release();
392   }
393 }
394 CFX_FloatRect CPDF_Array::GetRect() {
395   CFX_FloatRect rect;
396   if (m_Type != PDFOBJ_ARRAY || m_Objects.GetSize() != 4) {
397     return rect;
398   }
399   rect.left = GetNumber(0);
400   rect.bottom = GetNumber(1);
401   rect.right = GetNumber(2);
402   rect.top = GetNumber(3);
403   return rect;
404 }
405 CFX_AffineMatrix CPDF_Array::GetMatrix() {
406   CFX_AffineMatrix matrix;
407   if (m_Type != PDFOBJ_ARRAY || m_Objects.GetSize() != 6) {
408     return matrix;
409   }
410   matrix.Set(GetNumber(0), GetNumber(1), GetNumber(2), GetNumber(3),
411              GetNumber(4), GetNumber(5));
412   return matrix;
413 }
414 CPDF_Object* CPDF_Array::GetElement(FX_DWORD i) const {
415   if (i >= (FX_DWORD)m_Objects.GetSize()) {
416     return NULL;
417   }
418   return (CPDF_Object*)m_Objects.GetAt(i);
419 }
420 CPDF_Object* CPDF_Array::GetElementValue(FX_DWORD i) const {
421   if (i >= (FX_DWORD)m_Objects.GetSize()) {
422     return NULL;
423   }
424   return ((CPDF_Object*)m_Objects.GetAt(i))->GetDirect();
425 }
426 CFX_ByteString CPDF_Array::GetString(FX_DWORD i) const {
427   if (i < (FX_DWORD)m_Objects.GetSize()) {
428     CPDF_Object* p = (CPDF_Object*)m_Objects.GetAt(i);
429     return p->GetString();
430   }
431   return CFX_ByteString();
432 }
433 CFX_ByteStringC CPDF_Array::GetConstString(FX_DWORD i) const {
434   if (i < (FX_DWORD)m_Objects.GetSize()) {
435     CPDF_Object* p = (CPDF_Object*)m_Objects.GetAt(i);
436     return p->GetConstString();
437   }
438   return CFX_ByteStringC();
439 }
440 int CPDF_Array::GetInteger(FX_DWORD i) const {
441   if (i >= (FX_DWORD)m_Objects.GetSize()) {
442     return 0;
443   }
444   CPDF_Object* p = (CPDF_Object*)m_Objects.GetAt(i);
445   return p->GetInteger();
446 }
447 FX_FLOAT CPDF_Array::GetNumber(FX_DWORD i) const {
448   if (i >= (FX_DWORD)m_Objects.GetSize()) {
449     return 0;
450   }
451   CPDF_Object* p = (CPDF_Object*)m_Objects.GetAt(i);
452   return p->GetNumber();
453 }
454 CPDF_Dictionary* CPDF_Array::GetDict(FX_DWORD i) const {
455   CPDF_Object* p = GetElementValue(i);
456   if (!p) {
457     return NULL;
458   }
459   if (CPDF_Dictionary* pDict = p->AsDictionary()) {
460     return pDict;
461   }
462   if (p->GetType() == PDFOBJ_STREAM) {
463     return ((CPDF_Stream*)p)->GetDict();
464   }
465   return NULL;
466 }
467 CPDF_Stream* CPDF_Array::GetStream(FX_DWORD i) const {
468   CPDF_Object* p = GetElementValue(i);
469   if (p == NULL || p->GetType() != PDFOBJ_STREAM) {
470     return NULL;
471   }
472   return (CPDF_Stream*)p;
473 }
474 CPDF_Array* CPDF_Array::GetArray(FX_DWORD i) const {
475   CPDF_Object* p = GetElementValue(i);
476   if (p == NULL || p->GetType() != PDFOBJ_ARRAY) {
477     return NULL;
478   }
479   return (CPDF_Array*)p;
480 }
481 void CPDF_Array::RemoveAt(FX_DWORD i) {
482   ASSERT(m_Type == PDFOBJ_ARRAY);
483   if (i >= (FX_DWORD)m_Objects.GetSize()) {
484     return;
485   }
486   CPDF_Object* p = (CPDF_Object*)m_Objects.GetAt(i);
487   if (p)
488     p->Release();
489   m_Objects.RemoveAt(i);
490 }
491 void CPDF_Array::SetAt(FX_DWORD i,
492                        CPDF_Object* pObj,
493                        CPDF_IndirectObjects* pObjs) {
494   ASSERT(m_Type == PDFOBJ_ARRAY);
495   ASSERT(i < (FX_DWORD)m_Objects.GetSize());
496   if (i >= (FX_DWORD)m_Objects.GetSize()) {
497     return;
498   }
499   CPDF_Object* pOld = (CPDF_Object*)m_Objects.GetAt(i);
500   if (pOld)
501     pOld->Release();
502   if (pObj->GetObjNum()) {
503     ASSERT(pObjs != NULL);
504     pObj = new CPDF_Reference(pObjs, pObj->GetObjNum());
505   }
506   m_Objects.SetAt(i, pObj);
507 }
508 void CPDF_Array::InsertAt(FX_DWORD index,
509                           CPDF_Object* pObj,
510                           CPDF_IndirectObjects* pObjs) {
511   ASSERT(pObj != NULL);
512   if (pObj->GetObjNum()) {
513     ASSERT(pObjs != NULL);
514     pObj = new CPDF_Reference(pObjs, pObj->GetObjNum());
515   }
516   m_Objects.InsertAt(index, pObj);
517 }
518 void CPDF_Array::Add(CPDF_Object* pObj, CPDF_IndirectObjects* pObjs) {
519   ASSERT(pObj != NULL);
520   if (pObj->GetObjNum()) {
521     ASSERT(pObjs != NULL);
522     pObj = new CPDF_Reference(pObjs, pObj->GetObjNum());
523   }
524   m_Objects.Add(pObj);
525 }
526 void CPDF_Array::AddName(const CFX_ByteString& str) {
527   ASSERT(m_Type == PDFOBJ_ARRAY);
528   Add(new CPDF_Name(str));
529 }
530 void CPDF_Array::AddString(const CFX_ByteString& str) {
531   ASSERT(m_Type == PDFOBJ_ARRAY);
532   Add(new CPDF_String(str));
533 }
534 void CPDF_Array::AddInteger(int i) {
535   ASSERT(m_Type == PDFOBJ_ARRAY);
536   Add(new CPDF_Number(i));
537 }
538 void CPDF_Array::AddNumber(FX_FLOAT f) {
539   ASSERT(m_Type == PDFOBJ_ARRAY);
540   CPDF_Number* pNumber = new CPDF_Number;
541   pNumber->SetNumber(f);
542   Add(pNumber);
543 }
544 void CPDF_Array::AddReference(CPDF_IndirectObjects* pDoc, FX_DWORD objnum) {
545   ASSERT(m_Type == PDFOBJ_ARRAY);
546   Add(new CPDF_Reference(pDoc, objnum));
547 }
548 FX_BOOL CPDF_Array::Identical(CPDF_Array* pOther) const {
549   if (m_Objects.GetSize() != pOther->m_Objects.GetSize()) {
550     return FALSE;
551   }
552   for (int i = 0; i < m_Objects.GetSize(); i++)
553     if (!((CPDF_Object*)m_Objects[i])
554              ->IsIdentical((CPDF_Object*)pOther->m_Objects[i])) {
555       return FALSE;
556     }
557   return TRUE;
558 }
559 CPDF_Dictionary::~CPDF_Dictionary() {
560   FX_POSITION pos = m_Map.GetStartPosition();
561   while (pos) {
562     void* value = m_Map.GetNextValue(pos);
563     if (value)
564       ((CPDF_Object*)value)->Release();
565   }
566 }
567 FX_POSITION CPDF_Dictionary::GetStartPos() const {
568   return m_Map.GetStartPosition();
569 }
570 CPDF_Object* CPDF_Dictionary::GetNextElement(FX_POSITION& pos,
571                                              CFX_ByteString& key) const {
572   if (pos == NULL) {
573     return NULL;
574   }
575   CPDF_Object* p;
576   m_Map.GetNextAssoc(pos, key, (void*&)p);
577   return p;
578 }
579 CPDF_Object* CPDF_Dictionary::GetElement(const CFX_ByteStringC& key) const {
580   CPDF_Object* p = NULL;
581   m_Map.Lookup(key, (void*&)p);
582   return p;
583 }
584 CPDF_Object* CPDF_Dictionary::GetElementValue(
585     const CFX_ByteStringC& key) const {
586   CPDF_Object* p = NULL;
587   m_Map.Lookup(key, (void*&)p);
588   return p ? p->GetDirect() : NULL;
589 }
590 CFX_ByteString CPDF_Dictionary::GetString(const CFX_ByteStringC& key) const {
591   CPDF_Object* p = NULL;
592   m_Map.Lookup(key, (void*&)p);
593   if (p) {
594     return p->GetString();
595   }
596   return CFX_ByteString();
597 }
598 CFX_ByteStringC CPDF_Dictionary::GetConstString(
599     const CFX_ByteStringC& key) const {
600   CPDF_Object* p = NULL;
601   m_Map.Lookup(key, (void*&)p);
602   if (p) {
603     return p->GetConstString();
604   }
605   return CFX_ByteStringC();
606 }
607 CFX_WideString CPDF_Dictionary::GetUnicodeText(const CFX_ByteStringC& key,
608                                                CFX_CharMap* pCharMap) const {
609   CPDF_Object* p = NULL;
610   m_Map.Lookup(key, (void*&)p);
611   if (p) {
612     if (p->GetType() == PDFOBJ_REFERENCE) {
613       p = ((CPDF_Reference*)p)->GetDirect();
614       if (p) {
615         return p->GetUnicodeText(pCharMap);
616       }
617     } else {
618       return p->GetUnicodeText(pCharMap);
619     }
620   }
621   return CFX_WideString();
622 }
623 CFX_ByteString CPDF_Dictionary::GetString(const CFX_ByteStringC& key,
624                                           const CFX_ByteStringC& def) const {
625   CPDF_Object* p = NULL;
626   m_Map.Lookup(key, (void*&)p);
627   if (p) {
628     return p->GetString();
629   }
630   return CFX_ByteString(def);
631 }
632 CFX_ByteStringC CPDF_Dictionary::GetConstString(
633     const CFX_ByteStringC& key,
634     const CFX_ByteStringC& def) const {
635   CPDF_Object* p = NULL;
636   m_Map.Lookup(key, (void*&)p);
637   if (p) {
638     return p->GetConstString();
639   }
640   return CFX_ByteStringC(def);
641 }
642 int CPDF_Dictionary::GetInteger(const CFX_ByteStringC& key) const {
643   CPDF_Object* p = NULL;
644   m_Map.Lookup(key, (void*&)p);
645   if (p) {
646     return p->GetInteger();
647   }
648   return 0;
649 }
650 int CPDF_Dictionary::GetInteger(const CFX_ByteStringC& key, int def) const {
651   CPDF_Object* p = NULL;
652   m_Map.Lookup(key, (void*&)p);
653   if (p) {
654     return p->GetInteger();
655   }
656   return def;
657 }
658 FX_FLOAT CPDF_Dictionary::GetNumber(const CFX_ByteStringC& key) const {
659   CPDF_Object* p = NULL;
660   m_Map.Lookup(key, (void*&)p);
661   if (p) {
662     return p->GetNumber();
663   }
664   return 0;
665 }
666 FX_BOOL CPDF_Dictionary::GetBoolean(const CFX_ByteStringC& key,
667                                     FX_BOOL bDefault) const {
668   CPDF_Object* p = NULL;
669   m_Map.Lookup(key, (void*&)p);
670   if (ToBoolean(p))
671     return p->GetInteger();
672   return bDefault;
673 }
674 CPDF_Dictionary* CPDF_Dictionary::GetDict(const CFX_ByteStringC& key) const {
675   CPDF_Object* p = GetElementValue(key);
676   if (!p) {
677     return nullptr;
678   }
679   if (CPDF_Dictionary* pDict = p->AsDictionary()) {
680     return pDict;
681   }
682   if (p->GetType() == PDFOBJ_STREAM) {
683     return ((CPDF_Stream*)p)->GetDict();
684   }
685   return nullptr;
686 }
687 CPDF_Array* CPDF_Dictionary::GetArray(const CFX_ByteStringC& key) const {
688   CPDF_Object* p = GetElementValue(key);
689   if (p == NULL || p->GetType() != PDFOBJ_ARRAY) {
690     return NULL;
691   }
692   return (CPDF_Array*)p;
693 }
694 CPDF_Stream* CPDF_Dictionary::GetStream(const CFX_ByteStringC& key) const {
695   CPDF_Object* p = GetElementValue(key);
696   if (p == NULL || p->GetType() != PDFOBJ_STREAM) {
697     return NULL;
698   }
699   return (CPDF_Stream*)p;
700 }
701 CFX_FloatRect CPDF_Dictionary::GetRect(const CFX_ByteStringC& key) const {
702   CFX_FloatRect rect;
703   CPDF_Array* pArray = GetArray(key);
704   if (pArray) {
705     rect = pArray->GetRect();
706   }
707   return rect;
708 }
709 CFX_AffineMatrix CPDF_Dictionary::GetMatrix(const CFX_ByteStringC& key) const {
710   CFX_AffineMatrix matrix;
711   CPDF_Array* pArray = GetArray(key);
712   if (pArray) {
713     matrix = pArray->GetMatrix();
714   }
715   return matrix;
716 }
717 FX_BOOL CPDF_Dictionary::KeyExist(const CFX_ByteStringC& key) const {
718   void* value;
719   return m_Map.Lookup(key, value);
720 }
721 void CPDF_Dictionary::SetAt(const CFX_ByteStringC& key,
722                             CPDF_Object* pObj,
723                             CPDF_IndirectObjects* pObjs) {
724   ASSERT(m_Type == PDFOBJ_DICTIONARY);
725   CPDF_Object* p = NULL;
726   m_Map.Lookup(key, (void*&)p);
727   if (p == pObj) {
728     return;
729   }
730   if (p)
731     p->Release();
732   if (pObj) {
733     if (pObj->GetObjNum()) {
734       ASSERT(pObjs != NULL);
735       pObj = new CPDF_Reference(pObjs, pObj->GetObjNum());
736     }
737     m_Map.SetAt(key, pObj);
738   } else {
739     m_Map.RemoveKey(key);
740   }
741 }
742 void CPDF_Dictionary::AddValue(const CFX_ByteStringC& key, CPDF_Object* pObj) {
743   ASSERT(m_Type == PDFOBJ_DICTIONARY);
744   m_Map.AddValue(key, pObj);
745 }
746 void CPDF_Dictionary::RemoveAt(const CFX_ByteStringC& key) {
747   ASSERT(m_Type == PDFOBJ_DICTIONARY);
748   CPDF_Object* p = NULL;
749   m_Map.Lookup(key, (void*&)p);
750   if (p == NULL) {
751     return;
752   }
753   p->Release();
754   m_Map.RemoveKey(key);
755 }
756 void CPDF_Dictionary::ReplaceKey(const CFX_ByteStringC& oldkey,
757                                  const CFX_ByteStringC& newkey) {
758   ASSERT(m_Type == PDFOBJ_DICTIONARY);
759   CPDF_Object* p = NULL;
760   m_Map.Lookup(oldkey, (void*&)p);
761   if (p == NULL) {
762     return;
763   }
764   m_Map.RemoveKey(oldkey);
765   m_Map.SetAt(newkey, p);
766 }
767 FX_BOOL CPDF_Dictionary::Identical(CPDF_Dictionary* pOther) const {
768   if (pOther == NULL) {
769     return FALSE;
770   }
771   if (m_Map.GetCount() != pOther->m_Map.GetCount()) {
772     return FALSE;
773   }
774   FX_POSITION pos = m_Map.GetStartPosition();
775   while (pos) {
776     CFX_ByteString key;
777     void* value;
778     m_Map.GetNextAssoc(pos, key, value);
779     if (!value)
780       return FALSE;
781     if (!((CPDF_Object*)value)->IsIdentical(pOther->GetElement(key))) {
782       return FALSE;
783     }
784   }
785   return TRUE;
786 }
787 void CPDF_Dictionary::SetAtInteger(const CFX_ByteStringC& key, int i) {
788   SetAt(key, new CPDF_Number(i));
789 }
790 void CPDF_Dictionary::SetAtName(const CFX_ByteStringC& key,
791                                 const CFX_ByteString& name) {
792   SetAt(key, new CPDF_Name(name));
793 }
794 void CPDF_Dictionary::SetAtString(const CFX_ByteStringC& key,
795                                   const CFX_ByteString& str) {
796   SetAt(key, new CPDF_String(str));
797 }
798 void CPDF_Dictionary::SetAtReference(const CFX_ByteStringC& key,
799                                      CPDF_IndirectObjects* pDoc,
800                                      FX_DWORD objnum) {
801   SetAt(key, new CPDF_Reference(pDoc, objnum));
802 }
803 void CPDF_Dictionary::AddReference(const CFX_ByteStringC& key,
804                                    CPDF_IndirectObjects* pDoc,
805                                    FX_DWORD objnum) {
806   AddValue(key, new CPDF_Reference(pDoc, objnum));
807 }
808 void CPDF_Dictionary::SetAtNumber(const CFX_ByteStringC& key, FX_FLOAT f) {
809   CPDF_Number* pNumber = new CPDF_Number;
810   pNumber->SetNumber(f);
811   SetAt(key, pNumber);
812 }
813 void CPDF_Dictionary::SetAtBoolean(const CFX_ByteStringC& key, FX_BOOL bValue) {
814   SetAt(key, new CPDF_Boolean(bValue));
815 }
816 void CPDF_Dictionary::SetAtRect(const CFX_ByteStringC& key,
817                                 const CFX_FloatRect& rect) {
818   CPDF_Array* pArray = new CPDF_Array;
819   pArray->AddNumber(rect.left);
820   pArray->AddNumber(rect.bottom);
821   pArray->AddNumber(rect.right);
822   pArray->AddNumber(rect.top);
823   SetAt(key, pArray);
824 }
825 void CPDF_Dictionary::SetAtMatrix(const CFX_ByteStringC& key,
826                                   const CFX_AffineMatrix& matrix) {
827   CPDF_Array* pArray = new CPDF_Array;
828   pArray->AddNumber16(matrix.a);
829   pArray->AddNumber16(matrix.b);
830   pArray->AddNumber16(matrix.c);
831   pArray->AddNumber16(matrix.d);
832   pArray->AddNumber(matrix.e);
833   pArray->AddNumber(matrix.f);
834   SetAt(key, pArray);
835 }
836 CPDF_Stream::CPDF_Stream(uint8_t* pData, FX_DWORD size, CPDF_Dictionary* pDict)
837     : CPDF_Object(PDFOBJ_STREAM) {
838   m_pDict = pDict;
839   m_dwSize = size;
840   m_GenNum = (FX_DWORD)-1;
841   m_pDataBuf = pData;
842   m_pCryptoHandler = NULL;
843 }
844 CPDF_Stream::~CPDF_Stream() {
845   if (m_GenNum == (FX_DWORD)-1) {
846     FX_Free(m_pDataBuf);
847   }
848   if (m_pDict) {
849     m_pDict->Release();
850   }
851 }
852 void CPDF_Stream::InitStream(CPDF_Dictionary* pDict) {
853   if (pDict) {
854     if (m_pDict) {
855       m_pDict->Release();
856     }
857     m_pDict = pDict;
858   }
859   if (m_GenNum == (FX_DWORD)-1) {
860     FX_Free(m_pDataBuf);
861   }
862   m_GenNum = 0;
863   m_pFile = NULL;
864   m_pCryptoHandler = NULL;
865   m_FileOffset = 0;
866 }
867 void CPDF_Stream::InitStream(uint8_t* pData,
868                              FX_DWORD size,
869                              CPDF_Dictionary* pDict) {
870   InitStream(pDict);
871   m_GenNum = (FX_DWORD)-1;
872   m_pDataBuf = FX_Alloc(uint8_t, size);
873   if (pData) {
874     FXSYS_memcpy(m_pDataBuf, pData, size);
875   }
876   m_dwSize = size;
877   if (m_pDict) {
878     m_pDict->SetAtInteger(FX_BSTRC("Length"), size);
879   }
880 }
881 void CPDF_Stream::SetData(const uint8_t* pData,
882                           FX_DWORD size,
883                           FX_BOOL bCompressed,
884                           FX_BOOL bKeepBuf) {
885   if (m_GenNum == (FX_DWORD)-1) {
886     FX_Free(m_pDataBuf);
887   } else {
888     m_GenNum = (FX_DWORD)-1;
889     m_pCryptoHandler = NULL;
890   }
891   if (bKeepBuf) {
892     m_pDataBuf = (uint8_t*)pData;
893   } else {
894     m_pDataBuf = FX_Alloc(uint8_t, size);
895     if (pData) {
896       FXSYS_memcpy(m_pDataBuf, pData, size);
897     }
898   }
899   m_dwSize = size;
900   if (m_pDict == NULL) {
901     m_pDict = new CPDF_Dictionary;
902   }
903   m_pDict->SetAtInteger(FX_BSTRC("Length"), size);
904   if (!bCompressed) {
905     m_pDict->RemoveAt(FX_BSTRC("Filter"));
906     m_pDict->RemoveAt(FX_BSTRC("DecodeParms"));
907   }
908 }
909 FX_BOOL CPDF_Stream::ReadRawData(FX_FILESIZE offset,
910                                  uint8_t* buf,
911                                  FX_DWORD size) const {
912   if ((m_GenNum != (FX_DWORD)-1) && m_pFile) {
913     return m_pFile->ReadBlock(buf, m_FileOffset + offset, size);
914   }
915   if (m_pDataBuf) {
916     FXSYS_memcpy(buf, m_pDataBuf + offset, size);
917   }
918   return TRUE;
919 }
920 void CPDF_Stream::InitStream(IFX_FileRead* pFile, CPDF_Dictionary* pDict) {
921   InitStream(pDict);
922   m_pFile = pFile;
923   m_dwSize = (FX_DWORD)pFile->GetSize();
924   if (m_pDict) {
925     m_pDict->SetAtInteger(FX_BSTRC("Length"), m_dwSize);
926   }
927 }
928
929 FX_BOOL CPDF_Stream::Identical(CPDF_Stream* pOther) const {
930   if (!m_pDict)
931     return pOther->m_pDict ? FALSE : TRUE;
932
933   if (!m_pDict->Identical(pOther->m_pDict)) {
934     return FALSE;
935   }
936   if (m_dwSize != pOther->m_dwSize) {
937     return FALSE;
938   }
939   if (m_GenNum != (FX_DWORD)-1 && pOther->m_GenNum != (FX_DWORD)-1) {
940     if (m_pFile == pOther->m_pFile && m_pFile == NULL) {
941       return TRUE;
942     }
943     if (!m_pFile || !pOther->m_pFile) {
944       return FALSE;
945     }
946     uint8_t srcBuf[1024];
947     uint8_t destBuf[1024];
948     FX_DWORD size = m_dwSize;
949     FX_DWORD srcOffset = m_FileOffset;
950     FX_DWORD destOffset = pOther->m_FileOffset;
951     if (m_pFile == pOther->m_pFile && srcOffset == destOffset) {
952       return TRUE;
953     }
954     while (size > 0) {
955       FX_DWORD actualSize = size > 1024 ? 1024 : size;
956       m_pFile->ReadBlock(srcBuf, srcOffset, actualSize);
957       pOther->m_pFile->ReadBlock(destBuf, destOffset, actualSize);
958       if (FXSYS_memcmp(srcBuf, destBuf, actualSize) != 0) {
959         return FALSE;
960       }
961       size -= actualSize;
962       srcOffset += actualSize;
963       destOffset += actualSize;
964     }
965     return TRUE;
966   }
967   if (m_GenNum != (FX_DWORD)-1 || pOther->m_GenNum != (FX_DWORD)-1) {
968     IFX_FileRead* pFile = NULL;
969     uint8_t* pBuf = NULL;
970     FX_DWORD offset = 0;
971     if (pOther->m_GenNum != (FX_DWORD)-1) {
972       pFile = pOther->m_pFile;
973       pBuf = m_pDataBuf;
974       offset = pOther->m_FileOffset;
975     } else if (m_GenNum != (FX_DWORD)-1) {
976       pFile = m_pFile;
977       pBuf = pOther->m_pDataBuf;
978       offset = m_FileOffset;
979     }
980     if (NULL == pBuf) {
981       return FALSE;
982     }
983     uint8_t srcBuf[1024];
984     FX_DWORD size = m_dwSize;
985     while (size > 0) {
986       FX_DWORD actualSize = std::min(size, 1024U);
987       pFile->ReadBlock(srcBuf, offset, actualSize);
988       if (FXSYS_memcmp(srcBuf, pBuf, actualSize) != 0) {
989         return FALSE;
990       }
991       pBuf += actualSize;
992       size -= actualSize;
993       offset += actualSize;
994     }
995     return TRUE;
996   }
997   return FXSYS_memcmp(m_pDataBuf, pOther->m_pDataBuf, m_dwSize) == 0;
998 }
999
1000 CPDF_StreamAcc::CPDF_StreamAcc() {
1001   m_bNewBuf = FALSE;
1002   m_pData = NULL;
1003   m_dwSize = 0;
1004   m_pImageParam = NULL;
1005   m_pStream = NULL;
1006   m_pSrcData = NULL;
1007 }
1008 void CPDF_StreamAcc::LoadAllData(const CPDF_Stream* pStream,
1009                                  FX_BOOL bRawAccess,
1010                                  FX_DWORD estimated_size,
1011                                  FX_BOOL bImageAcc) {
1012   if (pStream == NULL || pStream->GetType() != PDFOBJ_STREAM) {
1013     return;
1014   }
1015   m_pStream = pStream;
1016   if (pStream->IsMemoryBased() &&
1017       (!pStream->GetDict()->KeyExist(FX_BSTRC("Filter")) || bRawAccess)) {
1018     m_dwSize = pStream->m_dwSize;
1019     m_pData = (uint8_t*)pStream->m_pDataBuf;
1020     return;
1021   }
1022   uint8_t* pSrcData;
1023   FX_DWORD dwSrcSize = pStream->m_dwSize;
1024   if (dwSrcSize == 0) {
1025     return;
1026   }
1027   if (!pStream->IsMemoryBased()) {
1028     pSrcData = m_pSrcData = FX_Alloc(uint8_t, dwSrcSize);
1029     if (!pStream->ReadRawData(0, pSrcData, dwSrcSize)) {
1030       return;
1031     }
1032   } else {
1033     pSrcData = pStream->m_pDataBuf;
1034   }
1035   uint8_t* pDecryptedData;
1036   FX_DWORD dwDecryptedSize;
1037   if (pStream->m_pCryptoHandler) {
1038     CFX_BinaryBuf dest_buf;
1039     dest_buf.EstimateSize(pStream->m_pCryptoHandler->DecryptGetSize(dwSrcSize));
1040     void* context = pStream->m_pCryptoHandler->DecryptStart(
1041         pStream->GetObjNum(), pStream->m_GenNum);
1042     pStream->m_pCryptoHandler->DecryptStream(context, pSrcData, dwSrcSize,
1043                                              dest_buf);
1044     pStream->m_pCryptoHandler->DecryptFinish(context, dest_buf);
1045     pDecryptedData = dest_buf.GetBuffer();
1046     dwDecryptedSize = dest_buf.GetSize();
1047     dest_buf.DetachBuffer();
1048   } else {
1049     pDecryptedData = pSrcData;
1050     dwDecryptedSize = dwSrcSize;
1051   }
1052   if (!pStream->GetDict()->KeyExist(FX_BSTRC("Filter")) || bRawAccess) {
1053     m_pData = pDecryptedData;
1054     m_dwSize = dwDecryptedSize;
1055   } else {
1056     FX_BOOL bRet = PDF_DataDecode(
1057         pDecryptedData, dwDecryptedSize, m_pStream->GetDict(), m_pData,
1058         m_dwSize, m_ImageDecoder, m_pImageParam, estimated_size, bImageAcc);
1059     if (!bRet) {
1060       m_pData = pDecryptedData;
1061       m_dwSize = dwDecryptedSize;
1062     }
1063   }
1064   if (pSrcData != pStream->m_pDataBuf && pSrcData != m_pData) {
1065     FX_Free(pSrcData);
1066   }
1067   if (pDecryptedData != pSrcData && pDecryptedData != m_pData) {
1068     FX_Free(pDecryptedData);
1069   }
1070   m_pSrcData = NULL;
1071   m_bNewBuf = m_pData != pStream->m_pDataBuf;
1072 }
1073 CPDF_StreamAcc::~CPDF_StreamAcc() {
1074   if (m_bNewBuf) {
1075     FX_Free(m_pData);
1076   }
1077   FX_Free(m_pSrcData);
1078 }
1079 const uint8_t* CPDF_StreamAcc::GetData() const {
1080   if (m_bNewBuf) {
1081     return m_pData;
1082   }
1083   if (!m_pStream) {
1084     return NULL;
1085   }
1086   return m_pStream->m_pDataBuf;
1087 }
1088 FX_DWORD CPDF_StreamAcc::GetSize() const {
1089   if (m_bNewBuf) {
1090     return m_dwSize;
1091   }
1092   if (!m_pStream) {
1093     return 0;
1094   }
1095   return m_pStream->m_dwSize;
1096 }
1097 uint8_t* CPDF_StreamAcc::DetachData() {
1098   if (m_bNewBuf) {
1099     uint8_t* p = m_pData;
1100     m_pData = NULL;
1101     m_dwSize = 0;
1102     return p;
1103   }
1104   uint8_t* p = FX_Alloc(uint8_t, m_dwSize);
1105   FXSYS_memcpy(p, m_pData, m_dwSize);
1106   return p;
1107 }
1108 void CPDF_Reference::SetRef(CPDF_IndirectObjects* pDoc, FX_DWORD objnum) {
1109   m_pObjList = pDoc;
1110   m_RefObjNum = objnum;
1111 }
1112 CPDF_IndirectObjects::CPDF_IndirectObjects(CPDF_Parser* pParser) {
1113   m_pParser = pParser;
1114   m_IndirectObjs.InitHashTable(1013);
1115   if (pParser) {
1116     m_LastObjNum = m_pParser->GetLastObjNum();
1117   } else {
1118     m_LastObjNum = 0;
1119   }
1120 }
1121 CPDF_IndirectObjects::~CPDF_IndirectObjects() {
1122   FX_POSITION pos = m_IndirectObjs.GetStartPosition();
1123   while (pos) {
1124     void* key;
1125     void* value;
1126     m_IndirectObjs.GetNextAssoc(pos, key, value);
1127     ((CPDF_Object*)value)->Destroy();
1128   }
1129 }
1130 CPDF_Object* CPDF_IndirectObjects::GetIndirectObject(
1131     FX_DWORD objnum,
1132     struct PARSE_CONTEXT* pContext) {
1133   if (objnum == 0) {
1134     return NULL;
1135   }
1136   void* value;
1137   {
1138     if (m_IndirectObjs.Lookup((void*)(uintptr_t)objnum, value)) {
1139       if (((CPDF_Object*)value)->GetObjNum() == -1) {
1140         return NULL;
1141       }
1142       return (CPDF_Object*)value;
1143     }
1144   }
1145   CPDF_Object* pObj = NULL;
1146   if (m_pParser) {
1147     pObj = m_pParser->ParseIndirectObject(this, objnum, pContext);
1148   }
1149   if (pObj == NULL) {
1150     return NULL;
1151   }
1152   pObj->m_ObjNum = objnum;
1153   if (m_LastObjNum < objnum) {
1154     m_LastObjNum = objnum;
1155   }
1156   if (m_IndirectObjs.Lookup((void*)(uintptr_t)objnum, value)) {
1157     if (value) {
1158       ((CPDF_Object*)value)->Destroy();
1159     }
1160   }
1161   m_IndirectObjs.SetAt((void*)(uintptr_t)objnum, pObj);
1162   return pObj;
1163 }
1164 int CPDF_IndirectObjects::GetIndirectType(FX_DWORD objnum) {
1165   void* value;
1166   if (m_IndirectObjs.Lookup((void*)(uintptr_t)objnum, value)) {
1167     return ((CPDF_Object*)value)->GetType();
1168   }
1169   if (m_pParser) {
1170     PARSE_CONTEXT context;
1171     FXSYS_memset(&context, 0, sizeof(PARSE_CONTEXT));
1172     context.m_Flags = PDFPARSE_TYPEONLY;
1173     return (int)(uintptr_t)m_pParser->ParseIndirectObject(this, objnum,
1174                                                           &context);
1175   }
1176   return 0;
1177 }
1178 FX_DWORD CPDF_IndirectObjects::AddIndirectObject(CPDF_Object* pObj) {
1179   if (pObj->m_ObjNum) {
1180     return pObj->m_ObjNum;
1181   }
1182   m_LastObjNum++;
1183   m_IndirectObjs.SetAt((void*)(uintptr_t)m_LastObjNum, pObj);
1184   pObj->m_ObjNum = m_LastObjNum;
1185   return m_LastObjNum;
1186 }
1187 void CPDF_IndirectObjects::ReleaseIndirectObject(FX_DWORD objnum) {
1188   void* value;
1189   if (!m_IndirectObjs.Lookup((void*)(uintptr_t)objnum, value)) {
1190     return;
1191   }
1192   if (((CPDF_Object*)value)->GetObjNum() == -1) {
1193     return;
1194   }
1195   ((CPDF_Object*)value)->Destroy();
1196   m_IndirectObjs.RemoveKey((void*)(uintptr_t)objnum);
1197 }
1198 void CPDF_IndirectObjects::InsertIndirectObject(FX_DWORD objnum,
1199                                                 CPDF_Object* pObj) {
1200   if (objnum == 0 || pObj == NULL) {
1201     return;
1202   }
1203   void* value = NULL;
1204   if (m_IndirectObjs.Lookup((void*)(uintptr_t)objnum, value)) {
1205     if (value) {
1206       if (pObj->GetGenNum() <= ((CPDF_Object*)value)->GetGenNum()) {
1207         return;
1208       }
1209       ((CPDF_Object*)value)->Destroy();
1210     }
1211   }
1212   pObj->m_ObjNum = objnum;
1213   m_IndirectObjs.SetAt((void*)(uintptr_t)objnum, pObj);
1214   if (m_LastObjNum < objnum) {
1215     m_LastObjNum = objnum;
1216   }
1217 }
1218 FX_DWORD CPDF_IndirectObjects::GetLastObjNum() const {
1219   return m_LastObjNum;
1220 }