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