OLD | NEW |
1 // Copyright 2014 PDFium Authors. All rights reserved. | 1 // Copyright 2014 PDFium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com | 5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com |
6 | 6 |
7 #include "core/include/fpdfapi/fpdf_objects.h" | 7 #include "core/include/fpdfapi/fpdf_objects.h" |
8 | 8 |
| 9 #include <algorithm> |
| 10 |
9 #include "core/include/fpdfapi/fpdf_parser.h" | 11 #include "core/include/fpdfapi/fpdf_parser.h" |
10 #include "core/include/fxcrt/fx_string.h" | 12 #include "core/include/fxcrt/fx_string.h" |
11 #include "third_party/base/stl_util.h" | 13 #include "third_party/base/stl_util.h" |
12 | 14 |
13 namespace { | 15 namespace { |
14 | 16 |
15 const FX_DWORD kBlockSize = 1024; | 17 const FX_DWORD kBlockSize = 1024; |
16 | 18 |
17 } // namespace | 19 } // namespace |
18 | 20 |
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
140 CPDF_Dictionary* CPDF_Object::GetDict() const { | 142 CPDF_Dictionary* CPDF_Object::GetDict() const { |
141 switch (m_Type) { | 143 switch (m_Type) { |
142 case PDFOBJ_DICTIONARY: | 144 case PDFOBJ_DICTIONARY: |
143 // The method should be made non-const if we want to not be const. | 145 // The method should be made non-const if we want to not be const. |
144 // See bug #234. | 146 // See bug #234. |
145 return const_cast<CPDF_Dictionary*>(AsDictionary()); | 147 return const_cast<CPDF_Dictionary*>(AsDictionary()); |
146 case PDFOBJ_STREAM: | 148 case PDFOBJ_STREAM: |
147 return AsStream()->GetDict(); | 149 return AsStream()->GetDict(); |
148 case PDFOBJ_REFERENCE: { | 150 case PDFOBJ_REFERENCE: { |
149 const CPDF_Reference* pRef = AsReference(); | 151 const CPDF_Reference* pRef = AsReference(); |
150 CPDF_IndirectObjects* pIndirect = pRef->GetObjList(); | 152 CPDF_IndirectObjectHolder* pIndirect = pRef->GetObjList(); |
151 if (!pIndirect) | 153 if (!pIndirect) |
152 return nullptr; | 154 return nullptr; |
153 CPDF_Object* pObj = | 155 CPDF_Object* pObj = |
154 pIndirect->GetIndirectObject(pRef->GetRefObjNum(), nullptr); | 156 pIndirect->GetIndirectObject(pRef->GetRefObjNum(), nullptr); |
155 if (!pObj || (pObj == this)) | 157 if (!pObj || (pObj == this)) |
156 return nullptr; | 158 return nullptr; |
157 return pObj->GetDict(); | 159 return pObj->GetDict(); |
158 } | 160 } |
159 default: | 161 default: |
160 return nullptr; | 162 return nullptr; |
(...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
293 if (bDirect && !pdfium::ContainsKey(*visited, obj_num)) { | 295 if (bDirect && !pdfium::ContainsKey(*visited, obj_num)) { |
294 visited->insert(obj_num); | 296 visited->insert(obj_num); |
295 auto* pDirect = pRef->GetDirect(); | 297 auto* pDirect = pRef->GetDirect(); |
296 return pDirect ? pDirect->CloneInternal(TRUE, visited) : nullptr; | 298 return pDirect ? pDirect->CloneInternal(TRUE, visited) : nullptr; |
297 } | 299 } |
298 return new CPDF_Reference(pRef->m_pObjList, obj_num); | 300 return new CPDF_Reference(pRef->m_pObjList, obj_num); |
299 } | 301 } |
300 } | 302 } |
301 return NULL; | 303 return NULL; |
302 } | 304 } |
303 CPDF_Object* CPDF_Object::CloneRef(CPDF_IndirectObjects* pDoc) const { | 305 CPDF_Object* CPDF_Object::CloneRef(CPDF_IndirectObjectHolder* pDoc) const { |
304 if (m_ObjNum) { | 306 if (m_ObjNum) { |
305 return new CPDF_Reference(pDoc, m_ObjNum); | 307 return new CPDF_Reference(pDoc, m_ObjNum); |
306 } | 308 } |
307 return Clone(); | 309 return Clone(); |
308 } | 310 } |
309 CFX_WideString CPDF_Object::GetUnicodeText(CFX_CharMap* pCharMap) const { | 311 CFX_WideString CPDF_Object::GetUnicodeText(CFX_CharMap* pCharMap) const { |
310 if (const CPDF_String* pString = AsString()) | 312 if (const CPDF_String* pString = AsString()) |
311 return PDF_DecodeText(pString->m_String, pCharMap); | 313 return PDF_DecodeText(pString->m_String, pCharMap); |
312 | 314 |
313 if (const CPDF_Stream* pStream = AsStream()) { | 315 if (const CPDF_Stream* pStream = AsStream()) { |
(...skipping 192 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
506 return; | 508 return; |
507 | 509 |
508 for (int j = 0; j < nCount; ++j) { | 510 for (int j = 0; j < nCount; ++j) { |
509 if (CPDF_Object* p = m_Objects.GetAt(i + j)) | 511 if (CPDF_Object* p = m_Objects.GetAt(i + j)) |
510 p->Release(); | 512 p->Release(); |
511 } | 513 } |
512 m_Objects.RemoveAt(i, nCount); | 514 m_Objects.RemoveAt(i, nCount); |
513 } | 515 } |
514 void CPDF_Array::SetAt(FX_DWORD i, | 516 void CPDF_Array::SetAt(FX_DWORD i, |
515 CPDF_Object* pObj, | 517 CPDF_Object* pObj, |
516 CPDF_IndirectObjects* pObjs) { | 518 CPDF_IndirectObjectHolder* pObjs) { |
517 ASSERT(IsArray()); | 519 ASSERT(IsArray()); |
518 ASSERT(i < (FX_DWORD)m_Objects.GetSize()); | 520 ASSERT(i < (FX_DWORD)m_Objects.GetSize()); |
519 if (i >= (FX_DWORD)m_Objects.GetSize()) | 521 if (i >= (FX_DWORD)m_Objects.GetSize()) |
520 return; | 522 return; |
521 if (CPDF_Object* pOld = m_Objects.GetAt(i)) | 523 if (CPDF_Object* pOld = m_Objects.GetAt(i)) |
522 pOld->Release(); | 524 pOld->Release(); |
523 if (pObj->GetObjNum()) { | 525 if (pObj->GetObjNum()) { |
524 ASSERT(pObjs); | 526 ASSERT(pObjs); |
525 pObj = new CPDF_Reference(pObjs, pObj->GetObjNum()); | 527 pObj = new CPDF_Reference(pObjs, pObj->GetObjNum()); |
526 } | 528 } |
527 m_Objects.SetAt(i, pObj); | 529 m_Objects.SetAt(i, pObj); |
528 } | 530 } |
529 void CPDF_Array::InsertAt(FX_DWORD index, | 531 void CPDF_Array::InsertAt(FX_DWORD index, |
530 CPDF_Object* pObj, | 532 CPDF_Object* pObj, |
531 CPDF_IndirectObjects* pObjs) { | 533 CPDF_IndirectObjectHolder* pObjs) { |
532 if (pObj->GetObjNum()) { | 534 if (pObj->GetObjNum()) { |
533 ASSERT(pObjs); | 535 ASSERT(pObjs); |
534 pObj = new CPDF_Reference(pObjs, pObj->GetObjNum()); | 536 pObj = new CPDF_Reference(pObjs, pObj->GetObjNum()); |
535 } | 537 } |
536 m_Objects.InsertAt(index, pObj); | 538 m_Objects.InsertAt(index, pObj); |
537 } | 539 } |
538 void CPDF_Array::Add(CPDF_Object* pObj, CPDF_IndirectObjects* pObjs) { | 540 void CPDF_Array::Add(CPDF_Object* pObj, CPDF_IndirectObjectHolder* pObjs) { |
539 if (pObj->GetObjNum()) { | 541 if (pObj->GetObjNum()) { |
540 ASSERT(pObjs); | 542 ASSERT(pObjs); |
541 pObj = new CPDF_Reference(pObjs, pObj->GetObjNum()); | 543 pObj = new CPDF_Reference(pObjs, pObj->GetObjNum()); |
542 } | 544 } |
543 m_Objects.Add(pObj); | 545 m_Objects.Add(pObj); |
544 } | 546 } |
545 void CPDF_Array::AddName(const CFX_ByteString& str) { | 547 void CPDF_Array::AddName(const CFX_ByteString& str) { |
546 ASSERT(IsArray()); | 548 ASSERT(IsArray()); |
547 Add(new CPDF_Name(str)); | 549 Add(new CPDF_Name(str)); |
548 } | 550 } |
549 void CPDF_Array::AddString(const CFX_ByteString& str) { | 551 void CPDF_Array::AddString(const CFX_ByteString& str) { |
550 ASSERT(IsArray()); | 552 ASSERT(IsArray()); |
551 Add(new CPDF_String(str, FALSE)); | 553 Add(new CPDF_String(str, FALSE)); |
552 } | 554 } |
553 void CPDF_Array::AddInteger(int i) { | 555 void CPDF_Array::AddInteger(int i) { |
554 ASSERT(IsArray()); | 556 ASSERT(IsArray()); |
555 Add(new CPDF_Number(i)); | 557 Add(new CPDF_Number(i)); |
556 } | 558 } |
557 void CPDF_Array::AddNumber(FX_FLOAT f) { | 559 void CPDF_Array::AddNumber(FX_FLOAT f) { |
558 ASSERT(IsArray()); | 560 ASSERT(IsArray()); |
559 CPDF_Number* pNumber = new CPDF_Number; | 561 CPDF_Number* pNumber = new CPDF_Number; |
560 pNumber->SetNumber(f); | 562 pNumber->SetNumber(f); |
561 Add(pNumber); | 563 Add(pNumber); |
562 } | 564 } |
563 void CPDF_Array::AddReference(CPDF_IndirectObjects* pDoc, FX_DWORD objnum) { | 565 void CPDF_Array::AddReference(CPDF_IndirectObjectHolder* pDoc, |
| 566 FX_DWORD objnum) { |
564 ASSERT(IsArray()); | 567 ASSERT(IsArray()); |
565 Add(new CPDF_Reference(pDoc, objnum)); | 568 Add(new CPDF_Reference(pDoc, objnum)); |
566 } | 569 } |
567 FX_BOOL CPDF_Array::Identical(CPDF_Array* pOther) const { | 570 FX_BOOL CPDF_Array::Identical(CPDF_Array* pOther) const { |
568 if (m_Objects.GetSize() != pOther->m_Objects.GetSize()) { | 571 if (m_Objects.GetSize() != pOther->m_Objects.GetSize()) { |
569 return FALSE; | 572 return FALSE; |
570 } | 573 } |
571 for (int i = 0; i < m_Objects.GetSize(); i++) { | 574 for (int i = 0; i < m_Objects.GetSize(); i++) { |
572 if (!m_Objects[i]->IsIdentical(pOther->m_Objects[i])) | 575 if (!m_Objects[i]->IsIdentical(pOther->m_Objects[i])) |
573 return FALSE; | 576 return FALSE; |
(...skipping 184 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
758 } | 761 } |
759 void CPDF_Dictionary::SetAtName(const CFX_ByteStringC& key, | 762 void CPDF_Dictionary::SetAtName(const CFX_ByteStringC& key, |
760 const CFX_ByteString& name) { | 763 const CFX_ByteString& name) { |
761 SetAt(key, new CPDF_Name(name)); | 764 SetAt(key, new CPDF_Name(name)); |
762 } | 765 } |
763 void CPDF_Dictionary::SetAtString(const CFX_ByteStringC& key, | 766 void CPDF_Dictionary::SetAtString(const CFX_ByteStringC& key, |
764 const CFX_ByteString& str) { | 767 const CFX_ByteString& str) { |
765 SetAt(key, new CPDF_String(str, FALSE)); | 768 SetAt(key, new CPDF_String(str, FALSE)); |
766 } | 769 } |
767 void CPDF_Dictionary::SetAtReference(const CFX_ByteStringC& key, | 770 void CPDF_Dictionary::SetAtReference(const CFX_ByteStringC& key, |
768 CPDF_IndirectObjects* pDoc, | 771 CPDF_IndirectObjectHolder* pDoc, |
769 FX_DWORD objnum) { | 772 FX_DWORD objnum) { |
770 SetAt(key, new CPDF_Reference(pDoc, objnum)); | 773 SetAt(key, new CPDF_Reference(pDoc, objnum)); |
771 } | 774 } |
772 void CPDF_Dictionary::AddReference(const CFX_ByteStringC& key, | 775 void CPDF_Dictionary::AddReference(const CFX_ByteStringC& key, |
773 CPDF_IndirectObjects* pDoc, | 776 CPDF_IndirectObjectHolder* pDoc, |
774 FX_DWORD objnum) { | 777 FX_DWORD objnum) { |
775 SetAt(key, new CPDF_Reference(pDoc, objnum)); | 778 SetAt(key, new CPDF_Reference(pDoc, objnum)); |
776 } | 779 } |
777 void CPDF_Dictionary::SetAtNumber(const CFX_ByteStringC& key, FX_FLOAT f) { | 780 void CPDF_Dictionary::SetAtNumber(const CFX_ByteStringC& key, FX_FLOAT f) { |
778 CPDF_Number* pNumber = new CPDF_Number; | 781 CPDF_Number* pNumber = new CPDF_Number; |
779 pNumber->SetNumber(f); | 782 pNumber->SetNumber(f); |
780 SetAt(key, pNumber); | 783 SetAt(key, pNumber); |
781 } | 784 } |
782 void CPDF_Dictionary::SetAtBoolean(const CFX_ByteStringC& key, FX_BOOL bValue) { | 785 void CPDF_Dictionary::SetAtBoolean(const CFX_ByteStringC& key, FX_BOOL bValue) { |
783 SetAt(key, new CPDF_Boolean(bValue)); | 786 SetAt(key, new CPDF_Boolean(bValue)); |
(...skipping 258 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1042 if (m_bNewBuf) { | 1045 if (m_bNewBuf) { |
1043 uint8_t* p = m_pData; | 1046 uint8_t* p = m_pData; |
1044 m_pData = NULL; | 1047 m_pData = NULL; |
1045 m_dwSize = 0; | 1048 m_dwSize = 0; |
1046 return p; | 1049 return p; |
1047 } | 1050 } |
1048 uint8_t* p = FX_Alloc(uint8_t, m_dwSize); | 1051 uint8_t* p = FX_Alloc(uint8_t, m_dwSize); |
1049 FXSYS_memcpy(p, m_pData, m_dwSize); | 1052 FXSYS_memcpy(p, m_pData, m_dwSize); |
1050 return p; | 1053 return p; |
1051 } | 1054 } |
1052 void CPDF_Reference::SetRef(CPDF_IndirectObjects* pDoc, FX_DWORD objnum) { | 1055 void CPDF_Reference::SetRef(CPDF_IndirectObjectHolder* pDoc, FX_DWORD objnum) { |
1053 m_pObjList = pDoc; | 1056 m_pObjList = pDoc; |
1054 m_RefObjNum = objnum; | 1057 m_RefObjNum = objnum; |
1055 } | 1058 } |
1056 CPDF_IndirectObjects::CPDF_IndirectObjects(CPDF_Parser* pParser) { | 1059 CPDF_IndirectObjectHolder::CPDF_IndirectObjectHolder(CPDF_Parser* pParser) |
1057 m_pParser = pParser; | 1060 : m_pParser(pParser), m_LastObjNum(0) { |
1058 m_IndirectObjs.InitHashTable(1013); | 1061 if (pParser) |
1059 if (pParser) { | |
1060 m_LastObjNum = m_pParser->GetLastObjNum(); | 1062 m_LastObjNum = m_pParser->GetLastObjNum(); |
1061 } else { | 1063 } |
1062 m_LastObjNum = 0; | 1064 CPDF_IndirectObjectHolder::~CPDF_IndirectObjectHolder() { |
| 1065 for (const auto& pair : m_IndirectObjs) { |
| 1066 pair.second->Destroy(); |
1063 } | 1067 } |
1064 } | 1068 } |
1065 CPDF_IndirectObjects::~CPDF_IndirectObjects() { | 1069 CPDF_Object* CPDF_IndirectObjectHolder::GetIndirectObject( |
1066 FX_POSITION pos = m_IndirectObjs.GetStartPosition(); | 1070 FX_DWORD objnum, |
1067 while (pos) { | 1071 PARSE_CONTEXT* pContext) { |
1068 void* key; | |
1069 void* value; | |
1070 m_IndirectObjs.GetNextAssoc(pos, key, value); | |
1071 static_cast<CPDF_Object*>(value)->Destroy(); | |
1072 } | |
1073 } | |
1074 CPDF_Object* CPDF_IndirectObjects::GetIndirectObject(FX_DWORD objnum, | |
1075 PARSE_CONTEXT* pContext) { | |
1076 if (objnum == 0) | 1072 if (objnum == 0) |
1077 return nullptr; | 1073 return nullptr; |
1078 void* value; | |
1079 if (m_IndirectObjs.Lookup((void*)(uintptr_t)objnum, value)) { | |
1080 CPDF_Object* pValue = static_cast<CPDF_Object*>(value); | |
1081 if (pValue->GetObjNum() == -1) | |
1082 return nullptr; | |
1083 return pValue; | |
1084 } | |
1085 | 1074 |
1086 CPDF_Object* pObj = nullptr; | 1075 auto it = m_IndirectObjs.find(objnum); |
1087 if (m_pParser) | 1076 if (it != m_IndirectObjs.end()) |
1088 pObj = m_pParser->ParseIndirectObject(this, objnum, pContext); | 1077 return it->second->GetObjNum() != -1 ? it->second : nullptr; |
| 1078 |
| 1079 if (!m_pParser) |
| 1080 return nullptr; |
| 1081 |
| 1082 CPDF_Object* pObj = m_pParser->ParseIndirectObject(this, objnum, pContext); |
1089 if (!pObj) | 1083 if (!pObj) |
1090 return nullptr; | 1084 return nullptr; |
1091 | 1085 |
1092 pObj->m_ObjNum = objnum; | 1086 pObj->m_ObjNum = objnum; |
1093 if (m_LastObjNum < objnum) { | 1087 m_LastObjNum = std::max(m_LastObjNum, objnum); |
1094 m_LastObjNum = objnum; | 1088 if (m_IndirectObjs[objnum]) |
1095 } | 1089 m_IndirectObjs[objnum]->Destroy(); |
1096 if (m_IndirectObjs.Lookup((void*)(uintptr_t)objnum, value)) { | 1090 |
1097 if (value) | 1091 m_IndirectObjs[objnum] = pObj; |
1098 static_cast<CPDF_Object*>(value)->Destroy(); | |
1099 } | |
1100 m_IndirectObjs.SetAt((void*)(uintptr_t)objnum, pObj); | |
1101 return pObj; | 1092 return pObj; |
1102 } | 1093 } |
1103 int CPDF_IndirectObjects::GetIndirectType(FX_DWORD objnum) { | 1094 int CPDF_IndirectObjectHolder::GetIndirectType(FX_DWORD objnum) { |
1104 void* value; | 1095 auto it = m_IndirectObjs.find(objnum); |
1105 if (m_IndirectObjs.Lookup((void*)(uintptr_t)objnum, value)) | 1096 if (it != m_IndirectObjs.end()) |
1106 return static_cast<CPDF_Object*>(value)->GetType(); | 1097 return it->second->GetType(); |
1107 | 1098 |
1108 if (m_pParser) { | 1099 if (!m_pParser) |
1109 PARSE_CONTEXT context; | 1100 return 0; |
1110 FXSYS_memset(&context, 0, sizeof(PARSE_CONTEXT)); | 1101 |
1111 context.m_Flags = PDFPARSE_TYPEONLY; | 1102 PARSE_CONTEXT context; |
1112 return (int)(uintptr_t)m_pParser->ParseIndirectObject(this, objnum, | 1103 FXSYS_memset(&context, 0, sizeof(PARSE_CONTEXT)); |
1113 &context); | 1104 context.m_Flags = PDFPARSE_TYPEONLY; |
1114 } | 1105 return (int)(uintptr_t)m_pParser->ParseIndirectObject(this, objnum, &context); |
1115 return 0; | |
1116 } | 1106 } |
1117 FX_DWORD CPDF_IndirectObjects::AddIndirectObject(CPDF_Object* pObj) { | 1107 FX_DWORD CPDF_IndirectObjectHolder::AddIndirectObject(CPDF_Object* pObj) { |
1118 if (pObj->m_ObjNum) { | 1108 if (pObj->m_ObjNum) { |
1119 return pObj->m_ObjNum; | 1109 return pObj->m_ObjNum; |
1120 } | 1110 } |
1121 m_LastObjNum++; | 1111 m_LastObjNum++; |
1122 m_IndirectObjs.SetAt((void*)(uintptr_t)m_LastObjNum, pObj); | 1112 m_IndirectObjs[m_LastObjNum] = pObj; |
1123 pObj->m_ObjNum = m_LastObjNum; | 1113 pObj->m_ObjNum = m_LastObjNum; |
1124 return m_LastObjNum; | 1114 return m_LastObjNum; |
1125 } | 1115 } |
1126 void CPDF_IndirectObjects::ReleaseIndirectObject(FX_DWORD objnum) { | 1116 void CPDF_IndirectObjectHolder::ReleaseIndirectObject(FX_DWORD objnum) { |
1127 void* value; | 1117 auto it = m_IndirectObjs.find(objnum); |
1128 if (!m_IndirectObjs.Lookup((void*)(uintptr_t)objnum, value)) | 1118 if (it == m_IndirectObjs.end() || it->second->GetObjNum() == -1) |
1129 return; | 1119 return; |
1130 CPDF_Object* pValue = static_cast<CPDF_Object*>(value); | 1120 it->second->Destroy(); |
1131 if (pValue->GetObjNum() == -1) | 1121 m_IndirectObjs.erase(it); |
1132 return; | |
1133 pValue->Destroy(); | |
1134 m_IndirectObjs.RemoveKey((void*)(uintptr_t)objnum); | |
1135 } | 1122 } |
1136 FX_BOOL CPDF_IndirectObjects::InsertIndirectObject(FX_DWORD objnum, | 1123 FX_BOOL CPDF_IndirectObjectHolder::InsertIndirectObject(FX_DWORD objnum, |
1137 CPDF_Object* pObj) { | 1124 CPDF_Object* pObj) { |
1138 if (!objnum || !pObj) | 1125 if (!objnum || !pObj) |
1139 return FALSE; | 1126 return FALSE; |
1140 void* value = nullptr; | 1127 auto it = m_IndirectObjs.find(objnum); |
1141 if (m_IndirectObjs.Lookup((void*)(uintptr_t)objnum, value)) { | 1128 if (it != m_IndirectObjs.end()) { |
1142 if (value) { | 1129 if (pObj->GetGenNum() <= it->second->GetGenNum()) { |
1143 CPDF_Object* pExistingObj = static_cast<CPDF_Object*>(value); | 1130 pObj->Destroy(); |
1144 if (pObj->GetGenNum() <= pExistingObj->GetGenNum()) { | 1131 return FALSE; |
1145 pObj->Destroy(); | |
1146 return FALSE; | |
1147 } | |
1148 pExistingObj->Destroy(); | |
1149 } | 1132 } |
| 1133 it->second->Destroy(); |
1150 } | 1134 } |
1151 pObj->m_ObjNum = objnum; | 1135 pObj->m_ObjNum = objnum; |
1152 m_IndirectObjs.SetAt((void*)(uintptr_t)objnum, pObj); | 1136 m_IndirectObjs[objnum] = pObj; |
1153 if (m_LastObjNum < objnum) | 1137 m_LastObjNum = std::max(m_LastObjNum, objnum); |
1154 m_LastObjNum = objnum; | |
1155 return TRUE; | 1138 return TRUE; |
1156 } | 1139 } |
1157 FX_DWORD CPDF_IndirectObjects::GetLastObjNum() const { | |
1158 return m_LastObjNum; | |
1159 } | |
OLD | NEW |